package com.imkenberg.mbean.avalon;

import org.jboss.system.ServiceMBeanSupport;



import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.Context;

import javax.rmi.PortableRemoteObject;


import javax.management.NotificationBroadcasterSupport;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.excalibur.component.ExcaliburComponentManager;
import org.apache.avalon.excalibur.component.RoleManager;
import org.apache.avalon.excalibur.component.ExcaliburComponentManagerCreator;
import org.apache.avalon.excalibur.component.DefaultRoleManager;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.component.ComponentManager;

import org.apache.log.Hierarchy;
import org.apache.log.LogTarget;
import org.apache.log.output.io.FileTarget;
import org.apache.log.format.ExtendedPatternFormatter;

import java.io.File;
import java.io.IOException;

import org.jboss.system.ServiceMBean;
import org.jboss.naming.NonSerializableFactory;

public class AvalonManager extends NotificationBroadcasterSupport implements  AvalonManagerMBean, ServiceMBean,MBeanRegistration{

  private String jndiName;
  private int state = ServiceMBean.STOPPED;
  MBeanServer server;
  ObjectName serviceName;
  private org.jboss.logging.Logger jbosslogger;

  private ExcaliburComponentManagerCreator ecmc;
  private String xconf="../avalon/xconf.xml";
  private String roles="../avalon/roles.xml";
  private String logconf="../avalon/logkit.xml";
  private String instrument = null;


  public AvalonManager(){
    jbosslogger =  org.jboss.logging.Logger.getLogger(getClass());
  }
  public String getXconf() {
    return xconf;
  }
  public void setXconf(String newXconf) {
    xconf = newXconf;
  }
  public void setRoles(String newRoles) {
    roles = newRoles;
  }
  public String getRoles() {
    return roles;
  }
  public void setLogconf(String newLog) {
    logconf = newLog;
  }
  public String getLogconf() {
    return logconf;
  }

  public void setInstrument(String newInstrument) {
    instrument = newInstrument;
  }
  public String getInstrument() {
    return instrument;
  }

  private void createExcaliburComponentManagerCreator() {
      File instrumentfile = null;
       try{
        if (instrument != null){
          instrumentfile = new File(instrument);
        }
        ecmc = new ExcaliburComponentManagerCreator( null, new File(logconf),
              new File(roles),new File(xconf),  instrumentfile);
      }
      catch(Exception e){
          jbosslogger.error("Error while createing Avalon Component Manager Creator",e);
      }

  }




  public String getJndiName()
  {
     return jndiName;
  }
  public void setJndiName(String jndiName) throws NamingException
  {
    String oldName = this.jndiName;
    this.jndiName = jndiName;
    if(getState() == STARTED )
    {
      unbind(oldName);
      try
      {
        rebind();
      }
      catch(Exception e)
      {
        NamingException ne = new
          NamingException("Failed to update jndiName");
        ne.setRootCause(e);
        throw ne;
      }
    }
  }

  public void start() throws Exception
  {
    state = STARTING;
    jbosslogger.info("Starting");
    createExcaliburComponentManagerCreator();
    if(ecmc != null) {
      rebind();
      state = STARTED;
      jbosslogger.info("Started");
    }
    else{
      jbosslogger.error("Faild to start Avalon Component Manager");
      state = FAILED;
    }
  }
  public void stop()
  {

    state = ServiceMBean.STOPPING;
    jbosslogger.info("Stopping");
    unbind(jndiName);
    ecmc.dispose();
    state = ServiceMBean.STOPPED;
    jbosslogger.info("Stopped");
  }

  private void rebind() throws NamingException
  {
    InitialContext rootCtx = new InitialContext();
    Name componentname = rootCtx.getNameParser("").parse(jndiName+ "ComponentManager");
    Name loggername = rootCtx.getNameParser("").parse(jndiName+ "LoggerManager");

    NonSerializableFactory.rebind(componentname ,ecmc.getComponentManager(), true);
    NonSerializableFactory.rebind(loggername,ecmc.getLoggerManager(), true);
    if(instrument != null){
      Name instrumentname = rootCtx.getNameParser("").parse(jndiName+ "InstrumentManager");
      NonSerializableFactory.rebind(instrumentname,ecmc.getInstrumentManager(), true);
    }
  }
  private void unbind(String jndiName)
  {
    try
    {
      InitialContext rootCtx = new InitialContext();
      rootCtx.unbind(jndiName+ "ComponentManager");
      rootCtx.unbind(jndiName+ "LoggerManager");
      if(instrument != null){;
        rootCtx.unbind(jndiName+ "InstrumentManager");
      }

      NonSerializableFactory.unbind(jndiName);
    }
    catch(NamingException e)
    {
      jbosslogger.error("Failed to unbind Avalonmanager", e);
    }
  }
  public String getName() {
      return "AvalonManager";
  }
  public int getState() {
    return state;
  }
  public String getStateString() {
    return states[state];

  }
  public void create() throws java.lang.Exception {
    jbosslogger.info("createing");
  }

  public void destroy() {

  }

  //*************************
      public ObjectName preRegister(MBeanServer server, ObjectName name)
      throws Exception
   {
      this.server = server;

      serviceName = name;

      return serviceName;
   }

   public void postRegister(Boolean registrationDone)
   {
      if (!registrationDone.booleanValue())
      {
         //log.info( "Registration is not done -> destroy" );
         stop();
      }
   }

   public void preDeregister() throws Exception { }
   public void postDeregister() { }



}
