package com.ttv.acs.jmx;

import java.util.Properties;

import org.apache.log4j.Logger;
import org.jboss.ejb3.annotation.Management;
import org.jboss.ejb3.annotation.Service;

import com.ttv.acs.util.ADIUtil;
import com.twc.isa.AssetModule.AssetFactory;
import com.twc.isa.AssetModule.AssetFactory_impl;
import com.twc.isa.ServerModule.ServantBase_impl;

/**
 * <b>AssetFactoryerviceMBean<b>. 
 * 
 * @author cbrown@tandbergtv.com
 *
 */
 @Service (objectName="acs:service=AssetFactoryServiceMBean")
 @Management (AssetFactoryService.class)
// @Depends ("jboss.j2ee:service=EARDeployment,url='ACSApplication.ear'")
 public class AssetFactoryServiceMBean implements AssetFactoryService {
	 
	 private final Logger log = Logger.getLogger(AssetFactoryServiceMBean.class);
	 
	 private AssetFactoryControl assetFactoryControl = null;
	 
	 // Lifecycle methods
	 
	 public void create() {;}
	 public void destroy() {;}
	 
	 public void 
	 start() throws Exception {
		 log.info("Starting Asset Factory.");
		 startAssetFactoryService();
	 }
	 
	 // Lifecycle method
	 public void 
	 stop() {
		 log.info("Stopping AssetFactory.");
		 stopAssetFactoryService();
	 }
	 
	 /**
	  * Start a AssetFactory.
	  */
	 public void
	 startAssetFactoryService() {
		 
		 if(assetFactoryControl == null) {
			 assetFactoryControl = new AssetFactoryControl();
			 assetFactoryControl.start();
		 } else {
			 log.debug("AssetFactory already running.");
		 }
	 }
	 
	 /**
	  * Stop the AssetFactory.
	  */
	 public void
	 stopAssetFactoryService() {
		 if(assetFactoryControl != null) {
			 assetFactoryControl.stopAssetFactory();
			 log.debug("AssetFactory signalled.");
		 }
	 }
	 
	 
	 /**
	  * 
	  * @author <a href="mailto:cbrown@tandbergtv.com">Corey Brown</a>
	  *
	  */
	 private class AssetFactoryControl extends Thread {
		 
		 private boolean stop = false;
		 
		 public void
		 stopAssetFactory() {
			 stop = true;
			 assetFactoryControl.interrupt();
		 }
		 
		 public void
		 run() {
			 
			 while(stop == false) {
				 
				 //
				 // Check to see if the CORBALOC is configured properly before proceeding.
				 //
				 
				 if(ADIUtil.getNameServerAddress() == null || ADIUtil.getNameServerAddress().length() == 0) {
					 try { Thread.sleep(60 * 1000); } catch(Exception ignore) {;}
					 continue;
				 }
			 
				 try {
					 startAssetFactory();
				 } catch(InterruptedException ie) {
					 if(stop == false) {
						 log.error("AssetFactory caught InterruptedException. Restart scheduled.");
					 } else {
						 log.error("AssetFactory Shutdown complete.");
					 }
				 } catch(Exception e) {
					 log.error("AssetFactory caught unexpected exception. Restart scheduled.", e);
				 }
				 
				 try {
					 Thread.sleep(5 * 1000);
				 } catch(Exception ignore) {;}
			 }
		 }
		 
		 private void
		 startAssetFactory() 
		 throws InterruptedException, Exception {
			 
			 org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(getOrbMainArgs(), getProperties());
			 
			 //
			 // Get the POA
			 //
			 
			 org.omg.PortableServer.POA rootPOA = org.omg.PortableServer.POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
			 
			 //
			 // Get the POA manager
			 //
			 
			 org.omg.PortableServer.POAManager manager = rootPOA.the_POAManager();
			 manager.activate();
			 
			 //
			 // Create the Factory and activate it.....
			 //
			 
			 AssetFactory_impl factoryImpl = new AssetFactory_impl(orb, "AssetFactory");
			 AssetFactory factory = factoryImpl._this(orb);
			 String[] serverPath = {"Factories", "AssetFactory"};
			 
			 factoryImpl.m_base.setFullPath(serverPath);
			 ServantBase_impl.setFactoryObject(orb, serverPath, factory);
			 
			 //
			 // Activate our object
			 //
			 
			 manager.activate();
			 
			 log.info("Bound AssetFactory to ior:" + factory.toString());
			 
			 //
			 // orb.run never returns. If it does, create a new server and rebind to the NS
			 //
			 
			 orb.run();
		 }
		 
		 private String[] 
		 getOrbMainArgs() {
			 String[] args = new String[2];
			 args[0] = "-ORBInitRef";
			 args[1] = "NameService=" + ADIUtil.getNameServerAddress();
			 return args;
		 }
		 
		 private Properties getProperties(){
				Properties p = new Properties();
				p.put("OAPort", ADIUtil.getAssetFactoryPort());
				return p;
			}
	 }
 }