/*********************************************************************
 * Copyright (c) 2004, 2007 Boeing
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Boeing - initial API and implementation
 **********************************************************************/

package org.eclipse.osee.ote.core.environment;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.ExportException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.eclipse.osee.connection.service.IServiceConnector;
import org.eclipse.osee.connection.service.LocalConnector;
import org.eclipse.osee.framework.jdk.core.reportdata.ReportDataListener;
import org.eclipse.osee.framework.jdk.core.util.EnhancedProperties;
import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.ote.OseeLogStatusCallback;
import org.eclipse.osee.ote.core.GCHelper;
import org.eclipse.osee.ote.core.OseeTestThread;
import org.eclipse.osee.ote.core.OteProperties;
import org.eclipse.osee.ote.core.TestPrompt;
import org.eclipse.osee.ote.core.TestScript;
import org.eclipse.osee.ote.core.enums.PromptResponseType;
import org.eclipse.osee.ote.core.environment.interfaces.IAssociatedObjectListener;
import org.eclipse.osee.ote.core.environment.interfaces.ICancelTimer;
import org.eclipse.osee.ote.core.environment.interfaces.IEnvironmentFactory;
import org.eclipse.osee.ote.core.environment.interfaces.IExecutionUnitManagement;
import org.eclipse.osee.ote.core.environment.interfaces.IRuntimeLibraryManager;
import org.eclipse.osee.ote.core.environment.interfaces.IScriptControl;
import org.eclipse.osee.ote.core.environment.interfaces.ITestEnvironment;
import org.eclipse.osee.ote.core.environment.interfaces.ITestEnvironmentAccessor;
import org.eclipse.osee.ote.core.environment.interfaces.ITestEnvironmentListener;
import org.eclipse.osee.ote.core.environment.interfaces.ITestLogger;
import org.eclipse.osee.ote.core.environment.interfaces.ITestStation;
import org.eclipse.osee.ote.core.environment.interfaces.ITimeout;
import org.eclipse.osee.ote.core.environment.interfaces.ITimerControl;
import org.eclipse.osee.ote.core.framework.IRunManager;
import org.eclipse.osee.ote.core.framework.command.ICommandHandle;
import org.eclipse.osee.ote.core.framework.command.ITestContext;
import org.eclipse.osee.ote.core.framework.command.ITestServerCommand;
import org.eclipse.osee.ote.core.internal.Activator;
import org.eclipse.osee.ote.properties.OtePropertiesCore;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

/**
 * @author Andrew M. Finkbeiner
 */
public abstract class TestEnvironment implements TestEnvironmentInterface, ITestEnvironmentAccessor, ITestContext {

   private final List<ITestEnvironmentListener> envListeners = new ArrayList<>(32);
   private IExecutionUnitManagement executionUnitManagement;

   private File outDir = null;
   private final ITestStation testStation;
   private boolean batchMode = false;
   private final HashMap<String, Remote> controlInterfaces = new HashMap<>();
   private final IEnvironmentFactory factory;
   private IServiceConnector connector;
   private final IRuntimeLibraryManager runtimeManager;

   @Deprecated
   private final HashMap<Class<?>, Object> associatedObjects;
   @Deprecated
   private final HashMap<Class<?>, ArrayList<IAssociatedObjectListener>> associatedObjectListeners;
   @Deprecated
   private boolean isEnvSetup = false;
   @Deprecated
   private final List<IScriptCompleteEvent> scriptCompleteListeners = new ArrayList<>();
   @Deprecated
   private final List<IScriptSetupEvent> scriptSetupListeners = new ArrayList<>();

   private volatile boolean isShutdown = false;
   private ServiceRegistration<TestEnvironmentInterface> myRegistration;

   private OteApi oteApi;

   protected TestEnvironment(IEnvironmentFactory factory) {
      GCHelper.getGCHelper().addRefWatch(this);
      this.factory = factory;
      this.testStation = factory.getTestStation();
      this.runtimeManager = factory.getRuntimeManager();

      this.associatedObjectListeners = new HashMap<>();
      this.associatedObjects = new HashMap<>(100);
      this.batchMode = OteProperties.isOseeOteInBatchModeEnabled();

   }

   public void init(IServiceConnector connector) {
      this.connector = connector;
   }

   private void setupDefaultConnector() {
      EnhancedProperties props = new EnhancedProperties();
      try {
         props.setProperty("station", InetAddress.getLocalHost().getHostName());
      } catch (UnknownHostException ex) {
         OseeLog.log(TestEnvironment.class, Level.SEVERE, ex);
      }
      props.setProperty("date", new Date());
      props.setProperty("group", "OSEE Test Environment");
      props.setProperty("owner", OtePropertiesCore.userName.getValue());
      connector = new LocalConnector(this, Integer.toString(this.getUniqueId()), props);
   }

   public ServiceTracker getServiceTracker(String clazz, ServiceTrackerCustomizer customizer) {
      return Activator.getInstance().getServiceTracker(clazz, customizer);
   }

   @Override
   public ServiceTracker getServiceTracker(String clazz) {
      return getServiceTracker(clazz, null);
   }

   @Override
   public ICommandHandle addCommand(ITestServerCommand cmd) throws ExportException {
      return factory.getCommandManager().addCommand(cmd, this);
   }

   @Override
   public IRunManager getRunManager() {
      return factory.getRunManager();
   }

   @Override
   public IRuntimeLibraryManager getRuntimeManager() {
      return this.runtimeManager;
   }

   @Override
   public IEnvironmentFactory getEnvironmentFactory() {
      return factory;
   }

   @Override
   public boolean isInBatchMode() {
      return batchMode;
   }

   @Override
   public void setBatchMode(boolean isInBatchMode) {
      if (!OteProperties.isOseeOteInBatchModeEnabled()) {
         this.batchMode = isInBatchMode;
      }
   }

   @Override
   public void addEnvironmentListener(ITestEnvironmentListener listener) {
      envListeners.add(listener);
   }

   @Override
   public boolean addTask(EnvironmentTask task) {
      factory.getTimerControl().addTask(task, this);
      return true;
   }

   public boolean equals(ITestEnvironment testEnvironment) throws RemoteException {
      if (testEnvironment.getUniqueId() == getUniqueId()) {
         return true;
      } else {
         return false;
      }
   }

   @Override
   public long getEnvTime() {
      return getTimerCtrl().getEnvTime();
   }

   @Override
   public IExecutionUnitManagement getExecutionUnitManagement() {
      return this.executionUnitManagement;
   }

   @Override
   public ITestLogger getLogger() {
      return factory.getTestLogger();
   }

   @Override
   public List<String> getQueueLabels() {
      List<String> list = new ArrayList<>();
      list.add("Description");
      return list;
   }

   @Override
   public abstract Object getModel(String modelClassName);

   @Override
   public IScriptControl getScriptCtrl() {
      return factory.getScriptControl();
   }

   @Override
   public byte[] getScriptOutfile(String filepath) throws RemoteException {
      try {
         File file = new File(filepath);
         InputStream is = new FileInputStream(file);
         long length = file.length();
         byte[] bytes = new byte[(int) length];

         int numRead = is.read(bytes);
         if (numRead < bytes.length) {
            throw new IOException("Could not completely read file " + file.getName());
         }
         is.close();
         OseeLog.log(TestEnvironment.class, Level.FINE, "going to send " + bytes.length + " bytes to the client");

         return bytes;
      } catch (Exception ex) {
         throw new RemoteException("Error retrieving the script output", ex);
      }
   }

   @Override
   public ITestStation getTestStation() {
      return testStation;
   }

   @Override
   public ITimerControl getTimerCtrl() {
      return factory.getTimerControl();
   }

   @Override
   public int getUniqueId() {
      return this.hashCode();
   }

   private final void removeAllTasks() {
      factory.getTimerControl().cancelAllTasks();
   }

   @Override
   public URL setBatchLibJar(byte[] batchJar) throws IOException {
      String path = OtePropertiesCore.userHome.getValue() + File.separator + TestEnvironment.class.getName();

      File dir = new File(path, "batchLibCache");
      if (!dir.isDirectory()) {
         dir.mkdir();
      }
      File jar = File.createTempFile("Batch", ".jar", dir);
      Lib.writeBytesToFile(batchJar, jar);
      return jar.toURI().toURL();
   }

   @Override
   public ICancelTimer setTimerFor(ITimeout listener, int time) {
      return getTimerCtrl().setTimerFor(listener, time);
   }

   @Override
   public void setupOutfileDir(String outfileDir) throws IOException {
      if (Strings.isValid(outfileDir)) {
         outDir = new File(outfileDir);
         if (!outDir.isDirectory()) {
            if (!outDir.mkdirs()) {
               throw new IOException("Failed to create the output directory");
            }
            OseeLog.logf(TestEnvironment.class, Level.INFO,
                  "Outfile Dir [%s] created.", outDir.getAbsolutePath());
         } else {
            OseeLog.logf(TestEnvironment.class, Level.FINE,
                  "Outfile Dir [%s] exists.", outDir.getAbsolutePath());
         }
      } else {
         throw new IOException("A valid outfile directory must be specified.");
      }
   }

   @Override
   public void shutdown() {
      if (isShutdown) {
         return;
      }
      isShutdown = true;
      runtimeManager.uninstall(new OseeLogStatusCallback());
      Activator.getInstance().unregisterTestEnvironment();
      // here we remove all environment tasks (emulators)
      removeAllTasks();
      if (associatedObjects != null) {
         this.associatedObjects.clear();// get rid of all models and support
      }

      OseeLog.log(TestEnvironment.class, Level.FINE, "shutting down environment");
      factory.getTimerControl().cancelTimers();
      stop();
      cleanupClassReferences();
      OseeTestThread.clearThreadReferences();
      for (ITestEnvironmentListener listener : envListeners) {
         try {
            listener.onEnvironmentKilled(this);
         } catch (Exception e) {
            OseeLog.log(TestEnvironment.class, Level.SEVERE, "exception during listener notification", e);
         }
      }
      envListeners.clear();
      if (getRunManager() != null) {
         getRunManager().clearAllListeners();
      }
   }

   protected abstract void loadExternalDrivers();

   public void startup(String outfileDir) throws Exception {
      try {
         setupOutfileDir(outfileDir);
      } catch (IOException ex) {
         throw new Exception("Error in directory setup. " + outfileDir, ex);
      }
      if (myRegistration != null) {
         myRegistration.unregister();
      }
      myRegistration = FrameworkUtil.getBundle(getClass()).getBundleContext().registerService(TestEnvironmentInterface.class, this, null);
   }

   protected void stop() {
      try {
         myRegistration.unregister();
      } catch (IllegalStateException ex) {
         // ignore if it's already unregistered
      }
   }

   protected void cleanupClassReferences() {
      OseeLog.log(TestEnvironment.class, Level.FINE, "cleanupreferences");

      System.out.println("Associated objects that are getting cleaned up.");
      for (Class<?> clazz : associatedObjects.keySet()) {
         System.out.println(clazz.toString());
      }

      if (associatedObjects != null) {
         associatedObjects.clear();
      }
      OseeLog.log(TestEnvironment.class, Level.FINE, "got the other PM REF");
      if (associatedObjectListeners != null) {
         associatedObjectListeners.clear();
      }
      GCHelper.getGCHelper().printLiveReferences();
   }

   public void setExecutionUnitManagement(IExecutionUnitManagement executionUnitManagement) {
      this.executionUnitManagement = executionUnitManagement;
   }

   @Override
   public File getOutDir() {
      return outDir;
   }

   @Override
   public Remote getControlInterface(String id) {
      return controlInterfaces.get(id);
   }

   @Override
   public void registerControlInterface(String id, Remote controlInterface) {
      controlInterfaces.put(id, controlInterface);
   }

   @Override
   public IServiceConnector getConnector() {
      return connector;
   }

   @Deprecated
   public void setEnvSetup(boolean isEnvSetup) {
      this.isEnvSetup = isEnvSetup;
   }

   @Deprecated
   public void addScriptCompleteListener(IScriptCompleteEvent scriptComplete) {
      this.scriptCompleteListeners.add(scriptComplete);
   }

   @Deprecated
   public void removeScriptCompleteListener(IScriptCompleteEvent scriptComplete) {
      this.scriptCompleteListeners.remove(scriptComplete);
   }

   @Deprecated
   public void addScriptSetupListener(IScriptSetupEvent scriptSetup) {
      this.scriptSetupListeners.add(scriptSetup);
   }

   @Deprecated
   public void removeScriptSetupListener(IScriptSetupEvent scriptSetup) {
      this.scriptSetupListeners.remove(scriptSetup);
   }

   @Deprecated
   protected boolean isEnvSetup() {
      return isEnvSetup;
   }

   @Deprecated
   /**
    * alerts the environment of an exception. The environment will take any
    * necessary actions and alert any interested
    * entities of the problem. Any runing test script will be terminated
    * 
    */
   public void handleException(Throwable t, Level logLevel) {
      handleException(t, "An exception has occurred in the environment", logLevel, true);
   }

   @Deprecated
   /**
    * @param abortScript
    *           true will cause the currently running script to abort
    */
   public void handleException(Throwable t, Level logLevel, boolean abortScript) {
      handleException(t, "An exception has occurred in the environment", logLevel, abortScript);
   }

   @Deprecated
   /**
    * alerts the environment of an exception. The environment will take any
    * necessary actions and alert any interested
    * entities of the problem
    * 
    * @param t
    *           the exception
    * @param logLevel
    *           the severity of the exception. Specifing a Level.OFF will
    * @param abortScript
    *           cause the exception to not be logged
    */
   public void handleException(Throwable t, String message, Level logLevel, boolean abortScript) {
      if (logLevel != Level.OFF) {
         OseeLog.log(TestEnvironment.class, logLevel, message, t);
      }
      if (getTestScript() != null && abortScript) {
         getTestScript().abortDueToThrowable(t);
      }
      Iterator<ITestEnvironmentListener> iter = envListeners.iterator();
      while (iter.hasNext()) {
         final ITestEnvironmentListener listener = iter.next();
         listener.onException(message, t);
      }
   }

   @Deprecated
   public void testEnvironmentCommandComplete(ICommandHandle handle) {
      for (ITestEnvironmentListener listener : envListeners) {
         try {
            listener.onTestServerCommandFinished(this, handle);
         } catch (Throwable th) {
            System.out.println(listener.getClass().getName());
            th.printStackTrace();
         }
      }
   }

   @Override
   @Deprecated
   /**
    * marks the script as ready as well as clears any objects that are
    * associated with the environment.
    */
   public synchronized void onScriptSetup() {

      for (IScriptSetupEvent listeners : scriptSetupListeners) {
         listeners.scriptSetup();
      }

      this.associatedObjects.clear();
   }

   @Deprecated
   public void removeQueueListener(ReportDataListener listener) throws RemoteException {
      factory.getReportDataControl().removeQueueListener(listener);
   }

   @Override
   @Deprecated
   public void onScriptComplete() throws InterruptedException {
      factory.getScriptControl().setScriptReady(false);

      for (int i = 0; i < scriptCompleteListeners.size(); i++) {
         try {
            scriptCompleteListeners.get(i).scriptComplete();
         } catch (Exception e) {
            OseeLog.log(TestEnvironment.class, Level.SEVERE, "problem with script complete listener", e);
         }
      }

      // here we remove all environment tasks (emulators)
      if (associatedObjects != null) {
         this.associatedObjects.clear();// get rid of all models and support
      }
   }

   @Override
   @Deprecated
   public void associateObject(Class<?> c, Object obj) {
      associatedObjects.put(c, obj);
      ArrayList<IAssociatedObjectListener> listeners = this.associatedObjectListeners.get(c);
      if (listeners != null) {
         for (int i = 0; i < listeners.size(); i++) {
            try {
               listeners.get(i).updateAssociatedListener();
            } catch (RemoteException e) {
               OseeLog.log(TestEnvironment.class, Level.SEVERE, e.getMessage(), e);
            }

         }
      }
   }

   @Override
   @Deprecated
   public Object getAssociatedObject(Class<?> c) {
      return associatedObjects.get(c);
   }

   @Override
   @Deprecated
   public Set<Class<?>> getAssociatedObjects() {
      return associatedObjects.keySet();
   }

   @Override
   @Deprecated
   /**
    * Use getRunManager().getCurrentScript() instead of this method.
    */
   public TestScript getTestScript() {
      return getRunManager().getCurrentScript();
   }

   /**
    * Causes current thread to wait until another thread invokes the {@link java.lang.Object#notify()}method or the
    * {@link java.lang.Object#notifyAll()}method for this object.
    * 
    * @param milliseconds
    * @throws InterruptedException
    */
   public void testWait(int milliseconds) {
      getRunManager().getCurrentScript().testWait(milliseconds);
   }
   
   @Override
   @Deprecated
   public void abortTestScript() {
      getRunManager().abort();
   }

   public OteApi getOteApi() {
      return oteApi;
   }

   public void setOteApi(OteApi oteApi) {
      this.oteApi = oteApi;
   }

   public void prompt() {
      getRunManager().getCurrentScript().prompt();
   }
   
   public void prompt(String message) {
      getRunManager().getCurrentScript().prompt(new TestPrompt(message, PromptResponseType.NONE));
   }
   
   public void promptPassFail(String message) {
      getRunManager().getCurrentScript().promptPassFail(message);
   }
   
   public void promptPause(String message) {
      getRunManager().getCurrentScript().promptPause(message);
   }
   
   public void promptStep(String message) {
      getRunManager().getCurrentScript().prompt(new TestPrompt(message, PromptResponseType.SCRIPT_STEP));
   }
   
   public String promptInput(String message) {
      return getRunManager().getCurrentScript().prompt(new TestPrompt(message, PromptResponseType.USER_INPUT));
   }
   
}
