/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.console.util;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.Iterator;
import java.util.List;

/**
 * Utility to take xml string and convert it to a javascript based tree within html.
 *
 * @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
 */
public class XMLToHTMLTreeBuilder
{
   /**
    * Expects the xml to string to be in same format as calling JNDIView.listXML().
    * Will then build a tree in html that uses javascript.  Depends on dtree.js script
    * being available.
    *
    * @param xml
    * @return
    * @throws DocumentException
    */
   public static String convertJNDIXML(String xml) throws DocumentException
   {
      Document jndiXml = DocumentHelper.parseText(xml);

      String scriptHead = "<div class=\"dtree\"><script type=\"text/javascript\" src=\"dtree.js\"></script>\n";

      String ejbTree = convertEjbModule(jndiXml);

      String contextTree = convertContext(jndiXml);

      return scriptHead + ejbTree + "<p>" + contextTree;
   }

   private static String convertContext(Document jndiXml)
   {
      StringBuffer html = new StringBuffer();

      Element jndiRoot = jndiXml.getRootElement();

      List contextRoot = jndiRoot.elements("context");
      int globalCounter = 0;
      if (contextRoot.size() > 0)
      {
         html.append(createTreeCommandLinks("contextTree"));

         // create tree and add root node
         html.append("<script type=\"text/javascript\">\n<!--\n");
         html.append("contextTree = new dTree('contextTree');\n");
         html.append("contextTree.add(" + globalCounter++ + ",-1,'JNDI Root Context');\n");


         int parentId = 0;

         Iterator itr = contextRoot.iterator();
         while (itr.hasNext())
         {
            Element contextElm = (Element) itr.next();
            String contextElmName = contextElm.getName();
            Element nameSub = contextElm.element("name");
            if (nameSub != null)
            {
               contextElmName = nameSub.getText();
            }
            //html.append("contextTree.add(" + globalCounter++ + ", " + parentId + "," + contextElmName + ");");
            html.append(add("contextTree", globalCounter++, parentId, contextElmName));
            //parentId++;

            String[] searchNames = new String[]{"context", "leaf"};

            globalCounter = buildTree(contextElm, searchNames, html, globalCounter, globalCounter - 1, "contextTree");

         }

         html.append("document.write(contextTree);");
         html.append("\n//-->\n</script>");
         html.append("\n</div>\n");
      }


      return html.toString();
   }

   private static String createTreeCommandLinks(String treeName)
   {
      return "<p><a href=\"javascript: " + treeName + ".openAll();\">Expands all</a> | <a href=\"javascript: " + treeName + ".closeAll();\">Collapse all</a></p>";
   }

   private static String convertEjbModule(Document jndiXml)
   {
      StringBuffer html = new StringBuffer();

      Element jndiRoot = jndiXml.getRootElement();

      List ejbModules = jndiRoot.elements("ejbmodule");
      int globalCounter = 0;
      if (ejbModules.size() > 0)
      {
         html.append(createTreeCommandLinks("ejbTree"));

         // create tree and add root node
         html.append("<script type=\"text/javascript\">\n<!--\n");
         html.append("ejbTree = new dTree('ejbTree');\n");
         html.append("ejbTree.add(" + globalCounter++ + ",-1,'EJB Modules');\n");


         int parentId = 0;

         Iterator itr = ejbModules.iterator();
         while (itr.hasNext())
         {
            Element ejbElm = (Element) itr.next();
            String ejbElmName = ejbElm.getName();
            //html.append("ejbTree.add(" + globalCounter++ + ", " + parentId + "," + ejbElmName + ");");
            html.append(add("ejbTree", globalCounter++, parentId, ejbElmName));
            parentId++;

            String[] searchNames = new String[]{"context", "leaf"};

            globalCounter = buildTree(ejbElm, searchNames, html, globalCounter, parentId, "ejbTree");


         }

         html.append("document.write(ejbTree);");
         html.append("\n//-->\n</script>");
      }


      return html.toString();
   }

   private static int buildTree(Element ejbElm, String[] searchNames, StringBuffer html,
                                int globalCounter, int parentId, String treeName)
   {
      if (searchNames != null)
      {
         for (int x = 0; x < searchNames.length; x++)
         {
            String searchName = searchNames[x];

            List contextElms = ejbElm.elements(searchName);
            Iterator elmItr = contextElms.iterator();
            while (elmItr.hasNext())
            {
               Element contextElm = (Element) elmItr.next();

               String name = "";
               String type = "";
               String typeValue = "";

               // check for context name
               Element nameElm = contextElm.element("name");
               if (nameElm != null)
               {
                  name = nameElm.getText();
               }
               Element attrElem = contextElm.element("attribute");
               if (attrElem != null)
               {
                  type = attrElem.attributeValue("name");
                  typeValue = attrElem.getText();
               }

               //html.append("treeName.add(" + globalCounter++ + ", " + parentId + ", '" + name + " -- " + type + "[" + typeValue + "]');");
               html.append(add(treeName, globalCounter++, parentId, name + " -- " + type + "[" + typeValue + "]"));

               // now recurse
               globalCounter = buildTree(contextElm, searchNames, html, globalCounter, globalCounter - 1, treeName);

            }
         }
      }
      return globalCounter;
   }

   private static String add(String tree, int global, int parent, String name)
   {
      return tree + ".add(" + global + ", " + parent + ", '" + name + "');\n";
   }


   public static void main(String[] args)
   {
      String xml = "<jndi>\n" +
            "\t<ejbmodule>\n" +
            "\t\t<file>null</file>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>java:comp</name>\n" +
            "\t\t\t<attribute name=\"bean\">MEJB</attribute>\n" +
            "\t\t\t<context>\n" +
            "\t\t\t\t<name>env</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>Server-Name</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">java.lang.String</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t</context>\n" +
            "\t\t</context>\n" +
            "\t</ejbmodule>\n" +
            "\t<context>\n" +
            "\t\t<name>java:</name>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>XAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>DefaultDS</name>\n" +
            "\t\t\t<attribute name=\"class\">javax.sql.DataSource</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>SecurityProxyFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.security.SubjectSecurityProxyFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>DefaultJMSProvider</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.jms.jndi.JBossMQProvider</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>comp</name>\n" +
            "\t\t\t<attribute name=\"class\">javax.naming.Context</attribute>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>ConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>JmsXA</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>jaas</name>\n" +
            "\t\t\t<attribute name=\"class\">javax.naming.Context</attribute>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>JmsXARealm</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.security.plugins.SecurityDomainContext</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>jbossmq</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.security.plugins.SecurityDomainContext</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>HsqlDbRealm</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.security.plugins.SecurityDomainContext</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t</context>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>timedCacheFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">javax.naming.Context</attribute>\n" +
            "\t\t\t<error>\n" +
            "\t\t\t\t<message>Failed to list contents of: timedCacheFactory, errmsg=null</message>\n" +
            "\t\t\t</error>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>TransactionPropagationContextExporter</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.tm.TransactionPropagationContextFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>Mail</name>\n" +
            "\t\t\t<attribute name=\"class\">javax.mail.Session</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>StdJMSPool</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.jms.asf.StdServerSessionPoolFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>TransactionPropagationContextImporter</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.tm.TransactionPropagationContextImporter</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>TransactionManager</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.tm.TxManager</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t</context>\n" +
            "\t<context>\n" +
            "\t\t<name>Global</name>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>jmx</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<context>\n" +
            "\t\t\t\t<name>invoker</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>RMIAdaptor</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">$Proxy38</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t</context>\n" +
            "\t\t\t<context>\n" +
            "\t\t\t\t<name>rmi</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t\t<link-ref>\n" +
            "\t\t\t\t\t<name>RMIAdaptor</name>\n" +
            "\t\t\t\t\t<link>jmx/invoker/RMIAdaptor</link>\n" +
            "\t\t\t\t\t<attribute name=\"class\">javax.naming.LinkRef</attribute>\n" +
            "\t\t\t\t</link-ref>\n" +
            "\t\t\t</context>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>OIL2XAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>HTTPXAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>ConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>UserTransactionSessionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">$Proxy13</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>HTTPConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>XAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>invokers</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<context>\n" +
            "\t\t\t\t<name>TCK3</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>pooled</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">org.jboss.invocation.pooled.interfaces.PooledInvokerProxy</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>jrmp</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>http</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">org.jboss.invocation.http.interfaces.HttpInvokerProxy</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t</context>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>UserTransaction</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.tm.usertx.client.ClientUserTransaction</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>RMIXAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>UIL2XAConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyXAConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>queue</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>A</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>testQueue</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>ex</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>DLQ</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>D</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>C</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>B</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyQueue</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t</context>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>topic</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>testDurableTopic</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyTopic</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>testTopic</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyTopic</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>securedTopic</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jboss.mq.SpyTopic</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t</context>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>console</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<leaf>\n" +
            "\t\t\t\t<name>PluginManager</name>\n" +
            "\t\t\t\t<attribute name=\"class\">$Proxy39</attribute>\n" +
            "\t\t\t</leaf>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>UIL2ConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>HiLoKeyGeneratorFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>RMIConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<context>\n" +
            "\t\t\t<name>ejb</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t<context>\n" +
            "\t\t\t\t<name>mgmt</name>\n" +
            "\t\t\t\t<attribute name=\"class\">org.jnp.interfaces.NamingContext</attribute>\n" +
            "\t\t\t\t<leaf>\n" +
            "\t\t\t\t\t<name>MEJB</name>\n" +
            "\t\t\t\t\t<attribute name=\"class\">$Proxy44</attribute>\n" +
            "\t\t\t\t</leaf>\n" +
            "\t\t\t</context>\n" +
            "\t\t</context>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>OIL2ConnectionFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.mq.SpyConnectionFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t\t<leaf>\n" +
            "\t\t\t<name>UUIDKeyGeneratorFactory</name>\n" +
            "\t\t\t<attribute name=\"class\">org.jboss.ejb.plugins.keygenerator.uuid.UUIDKeyGeneratorFactory</attribute>\n" +
            "\t\t</leaf>\n" +
            "\t</context>\n" +
            "</jndi>";

      String html = null;
      try
      {
         html = XMLToHTMLTreeBuilder.convertJNDIXML(xml);
      }
      catch (DocumentException e)
      {
         e.printStackTrace();
      }
      System.out.println("HTML output:\n\n" + html);
   }

}