/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.media.engine;

import java.net.URL;
import java.util.Iterator;
import java.util.Vector;

import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.jboss.deployment.DeploymentException;
import org.jboss.logging.Logger;
import org.jboss.media.emb.CaptureMetaData;
import org.jboss.mx.util.MBeanProxy;
import org.jboss.mx.util.MBeanProxyCreationException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @version <tt>$Revision: 1.3 $</tt>
 * @author <a href="mailto:spyridon_samothrakis@yahoo.com">Spyridon Samothrakis</a>
 */
public class MediaXmlLoader
{
   public static final String PUBLISHER_FACTORY_TAG = "publisher-factory";

   public static final String PUBLISHER_TAG = "publisher";
   public static final String PUBLISHER_CLASS = "class";
   public static final String PUBLISHER_HOST = "host";
   public static final String PUBLISHER_PORT = "port";
   public static final String PUBLISHER_CONTEXT = "context";
   public static final String PUBLISHER_START = "true";

   public static final String TRANCODER_TAG = "transcoder-name";
   public static final String PLUGIN_REGISTRY_TAG = "plugin-registry-name";

   public static final String PLUGIN_GRAPH_TAG = "plugin-graph";
   public static final String PLUGIN_TAG = "plugin";
   public static final String PLUGIN_NAME_ATT = "name";

   public static final String CAPTURE_DEVICE_TAG = "capture";
   public static final String CAPTURE_DEVICE_NAME_ATT = "device";
   public static final String CAPTURA_DEVICE_TYPE_ATT = "type";

   public static final String SOURCE = "source";
   public static final String FILE_NAME = "file-name";

   private static Logger log = Logger.getLogger(MediaXmlLoader.class);

   public static boolean deployXML(Document doc, URL url, MBeanServer server)
      throws
         MalformedObjectNameException,
         DOMException,
         DeploymentException,
         MediaPluginGraphException
   {

      ObjectName m_factory;

      ObjectName m_name;
      MediaPluginRegistryMBean reg = null;

      m_factory = null;

      String publisher = "";
      String publisher_class = "";
      String publisher_host = "";
      String publisher_port = "";
      String publisher_context = "";

      ObjectName transcoder = null;

      ObjectName pluginRegistry = null;
      MediaPluginGraph pluginGraph = null;

      CaptureMetaData captureMetadata = null;

      String source = null;

      int pluginNum = 0;

      Vector extraAttributes = new Vector();
      boolean shouldStart = false;

      NodeList children = doc.getDocumentElement().getChildNodes();
      for (int i = 0; i < children.getLength(); i++)
      {
         if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
         {
            Element element = (Element) children.item(i);
            String tag = element.getTagName();

            if (tag.equals(PUBLISHER_FACTORY_TAG))
            {
               m_factory =
                  new ObjectName(
                     element.getChildNodes().item(0).getNodeValue());

            }

            else if (tag.equals(PUBLISHER_TAG))
            {
               publisher_class = element.getAttribute(PUBLISHER_CLASS);
               publisher_host = element.getAttribute(PUBLISHER_HOST);
               publisher_port = element.getAttribute(PUBLISHER_PORT);
               publisher_context = element.getAttribute(PUBLISHER_CONTEXT);

               NodeList attributes = element.getChildNodes();

               // seek the extra attributes and set them
               for (int k = 0; k < attributes.getLength(); k++)
               {
                  if (attributes.item(k).getNodeType() == Node.ELEMENT_NODE)
                  {
                     Element attribute = (Element) attributes.item(k);
                     String name = attribute.getAttribute("name");
                     String value =
                        attribute.getChildNodes().item(0).getNodeValue();
                     // soooooo lame
                     Attribute at = null;
                     try
                     {

                        at = new Attribute(name, Integer.decode(value));
                     }
                     catch (NumberFormatException e)
                     {
                        at = new Attribute(name, value);
                     }

                     //gotcha!!!
                     log.info(name + "=" + value);
                     extraAttributes.add(at);
                  }

               }

               if (element.getAttribute("start").equals("true"))
               {
                  shouldStart = true;
               }

            }

            else if (tag.equals(TRANCODER_TAG))
            {
               // transcoder = new ObjectName(element.getChildNodes().item(0).getNodeValue());
            }

            else if (tag.equals(PLUGIN_REGISTRY_TAG))
            {
               pluginRegistry =
                  new ObjectName(
                     element.getChildNodes().item(0).getNodeValue());

               try
               {
                  reg =
                     (MediaPluginRegistryMBean) MBeanProxy.create(
                        MediaPluginRegistry.class,
                        MediaPluginRegistryMBean.class,
                        pluginRegistry,
                        server);
               }
               catch (MBeanProxyCreationException e)
               {
                  // TODO: Added just to compile!
                  log.error("MBeanProxyCreationException", e);
               }
            }

            else if (tag.equals(PLUGIN_GRAPH_TAG))
            {
               pluginGraph = new MediaPluginGraph();
               NodeList plugins = element.getChildNodes();

               for (int k = 0; k < plugins.getLength(); k++)
               {
                  if (plugins.item(k).getNodeType() == Node.ELEMENT_NODE)
                  {
                     Element pluginElement = (Element) plugins.item(k);
                     String plugin = pluginElement.getTagName();

                     // if (plugin.equals(PLUGIN_TAG))
                     //{

                     String pluginName =
                        pluginElement.getAttribute(PLUGIN_NAME_ATT);
                     log.info("plugin " + pluginNum + "is " + pluginName);
                     pluginGraph.addPlugin(
                        reg.getPlugin(pluginName),
                        pluginNum);
                     pluginNum++;

                     //}
                  }
               }
            }

            else if (tag.equals(CAPTURE_DEVICE_TAG))
            {
               //captureMetadata.setDeviceName();
            }

            else if (tag.equals(SOURCE))
            {
               source = element.getAttribute(FILE_NAME);
            }

            else
            {
               log.warn("Unknown EMB tag: " + tag);
            }
         }
      }

      log.info(m_factory);
      log.info(publisher);
      log.info(publisher_class);
      log.info(publisher_host);
      log.info(publisher_port);
      log.info(publisher_context);

      log.info(transcoder);

      log.info(pluginRegistry);
      log.info(pluginGraph);

      log.info(captureMetadata);

      log.info(source);

      MediaPublisherFactoryMBean pub = null;

      try
      {
         // get the media publisher
         pub =
            (MediaPublisherFactoryMBean) MBeanProxy.create(
               MediaPublisherFactory.class,
               MediaPublisherFactoryMBean.class,
               m_factory,
               server);
      }
      catch (MBeanProxyCreationException e)
      {
         // TODO: Added just to compile!
         log.error("MBeanProxyCreationException", e);
      }

      ObjectName result =
         pub.createPublisher(
            publisher_class,
            publisher_context,
            publisher_host,
            Integer.parseInt(publisher_port),
            publisher,
            source);

      for (Iterator iter = extraAttributes.iterator(); iter.hasNext();)
      {
         Attribute at = (Attribute) iter.next();

         try
         {
            server.setAttribute(result, at);
         }
         catch (InstanceNotFoundException e)
         {
            log.error(e);
         }
         catch (AttributeNotFoundException e)
         {
            log.error(e);
         }
         catch (InvalidAttributeValueException e)
         {
            log.error(e);
         }
         catch (MBeanException e)
         {
            log.error(e);
         }
         catch (ReflectionException e)
         {
            log.error(e);
         }

      }

      MediaPublisherMBean pubObj = null;

      try
      {
         pubObj =
            (MediaPublisherMBean) MBeanProxy.create(
               MediaPublisher.class,
               MediaPublisherMBean.class,
               result,
               server);
      }
      catch (MBeanProxyCreationException e)
      {
         // TODO: Added just to compile!
         log.error("MBeanProxyCreationException", e);
      }

      pubObj.addPluginGraph(pluginGraph);

      if (shouldStart)
      {
         try
         {
            pubObj.publish();
         }
         catch (Exception e)
         {
            log.error("Could not start publisher", e);
         }
      }

      return true;
   }

   /**
    * @param document
    * @param url
    * @param server
    */
   public static void undeploy(Document doc, URL url, MBeanServer server)
      throws MalformedObjectNameException, NullPointerException, DOMException
   {
      String publisher_class = "";
      String publisher = "";
      String publisher_context = "";

      ObjectName m_factory = null;

      NodeList children = doc.getDocumentElement().getChildNodes();
      for (int i = 0; i < children.getLength(); i++)
      {
         if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
         {
            Element element = (Element) children.item(i);
            String tag = element.getTagName();

            if (tag.equals(PUBLISHER_FACTORY_TAG))
            {
               m_factory =
                  new ObjectName(
                     element.getChildNodes().item(0).getNodeValue());

            }

            else if (tag.equals(PUBLISHER_TAG))
            {
               publisher = element.getChildNodes().item(0).getNodeValue();
               publisher_class = element.getAttribute(PUBLISHER_CLASS);
               publisher_context = element.getAttribute(PUBLISHER_CONTEXT);
            }
         }
      }

      MediaPublisherFactoryMBean pub = null;

      try
      {
         // get the media publisher
         pub =
            (MediaPublisherFactoryMBean) MBeanProxy.create(
               MediaPublisherFactory.class,
               MediaPublisherFactoryMBean.class,
               m_factory,
               server);
      }
      catch (MBeanProxyCreationException e)
      {
         // TODO: Added just to compile!
         log.error("MBeanProxyCreationException", e);
      }

      ObjectName m_name = pub.getObjectName(publisher_class, publisher_context);
      pub.destroyPublisher(m_name);

   }
}