package bilab;

//import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
//import org.eclipse.core.runtime.Path;
//import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.plugin.*;
//import org.eclipse.swt.widgets.*;

//import jalview.AlignmentPanel;
//import jalview.DrawableSequence;
//import jalview.FormatAdapter;
//import jalview.ScorePanel;
//import jalview.ScoreSequence;
//import jalview.Sequence;

import java.util.*;
//import java.awt.BorderLayout;
//import java.awt.Frame;
import java.io.*;
import java.net.URL;

import org.python.util.PythonInterpreter; 
//import org.python.core.*; 

import bilab.notebook.FileSystemNotebookStore;


import scigol.*;



/**
 * The main plugin class to be used in the desktop.
 */
public class BilabPlugin extends AbstractUIPlugin
{
  //The singleton instance.
  private static BilabPlugin plugin = null;

  
  public static BilabPlugin getInstance()
  {
    if (plugin == null)
      plugin = new BilabPlugin();
    return plugin;
  }
  
  public static BilabPlugin getDefault()
  { 
    return getInstance(); 
   }
  
  
  
  // resource manager
  private ResourceManager resourceManager = null;
  
  public AddOnManager addOnManager = null;

  // Python interpreter instance
  PythonInterpreter python;
  

  /**
   * The constructor.
   */
  public BilabPlugin()
  {
    super();
    
    // create singelton instance
    if (plugin != null)
      Notify.devError(this,"BilabPlugin is a singleton - it can only be instantiated once");
    plugin = this;
    
    
    resourceManager = new ResourceManager(this,"bilab.BilabPluginResources");
    globalScope = NamespaceScope.newGlobalNamespaceScope();
    executor = new InterpretExecutor(globalScope);
    addOnManager = new AddOnManager(resourceManager, executor);

  }

  
  public static ResourceManager getResourceManager()
  {
    return getInstance().resourceManager;
  }
  
  
  public static AddOnManager getAddOnManager()
  {
    return getInstance().addOnManager;
  }
  
  public static ISourceExecutor getExecutor()
  {
    return getInstance().executor;
  }
  
  
  /**
   * This method is called upon plug-in activation
   */
  public void start(BundleContext context) throws Exception
  {
    super.start(context);
    
    
//!!!!!!!!!!!!!!!!!!!    
//!!! testing area
/*    
    try {
    
    // JalView
    Frame f = new Frame("SeqPanel");
    
    Sequence[] seq = FormatAdapter.read("U:\\dev\\GTL\\win\\BiLabRCP\\BiLab\\resources\\sequences\\cxcr_multi_seq.msf","File","MSF");
    ScoreSequence[] s = new ScoreSequence[seq.length];
    for (int i=0;i < seq.length;i++) {
      s[i] = new ScoreSequence(seq[i]);
    }
    DrawableSequence[] s1 = new DrawableSequence[seq.length];
    for (int i=0;i < seq.length;i++) {
      s1[i] = new DrawableSequence(seq[i]);
    }
    
    AlignmentPanel ap = new AlignmentPanel(null,s1);
    ScorePanel sp = new ScorePanel(null,s);
    //ap.setScorePanel(sp);
    f.setLayout(new BorderLayout());
    f.add("Center",ap);
    f.add("South",sp);
    f.resize(700,500);
    //f.pack();
    f.show();
    //!!! JalView
     
      
      
      
      //String[] args = new String[] { "U:\\dev\\GTL\\win\\BiLabRCP\\BiLab\\resources\\molecules\\AF084455.embl" };
      //uk.ac.sanger.artemis.components.ArtemisMain.main(new String[0]);
    
    } catch (Exception e) {
      Notify.devWarning(this,"exception in Artemis:"+e);
      e.printStackTrace();
      //Debug.WL(""+e);
    }
    
    //SQLiteTest.test();
*/    
    /*
try {
FileSystemNotebookStore store = FileSystemNotebookStore.getInstance();
String loc = "/C:/Documents and Settings/jungd/Desktop/tmp";
Notify.debug(this,"exists? "+(store.existsNotebook(loc+"/MyNotebook")));

String uri = null;
if (!store.existsNotebook(loc+"/MyNotebook")) {
  Notify.debug(this,"creating notebook MyNotebook in "+loc);
  uri = store.createNotebook(loc,"MyNotebook");
  Notify.debug(this,"resulting URI:"+uri);
  store.createSection(uri,"Introduction",null);
}
else {
  uri = store.getCurrentNotebookVersion(loc+"/MyNotebook");
  Notify.debug(this,"notebook URI:"+uri);
}

Notify.debug(this,"exists? "+(store.existsNotebook(uri)));

String[] versions = store.listNotebookVersionURIs(uri);
for(String ver : versions) Notify.debug("  version:"+ver);

Notify.debug("current version="+store.getCurrentNotebookVersion("file:///C:/Documents%20and%20Settings/jungd/Desktop/tmp/MyNotebook?version=another&page=5"));

Notify.debug("current section count="+store.getSectionCount(uri));
Notify.debug("current section[1] URI="+store.getSectionURI(uri,1));
Notify.debug("current section[2] URI="+store.getSectionURI(uri,2));
//store.deleteNotebookAll(uri);

} catch (Exception e) {
  e.printStackTrace();
  Notify.devError(this,"got exception:"+e.getMessage());
}
*/
    
    
//!!!
//!!!!!!!!! end testing area
    

    
    // load libraries
    Notify.logInfo(this,"Loading libraries");
    loadLibrary("biojava-1.4pre1.jar");
    loadLibrary("jakarta-regexp-1.2.jar");
    loadLibrary("commons-collections-2.1.jar");
    loadLibrary("jobcontrol.jar");
    loadLibrary("Jmol.jar");
    loadLibrary("Ice.jar");
    //loadLibrary("jython/jython.jar");
    
    
    // register some select classes
    NamespaceScope.registerLibraryClass("bilab","seq");
    NamespaceScope.registerLibraryClass("bilab","DNA");
    NamespaceScope.registerLibraryClass("bilab","RNA");
    NamespaceScope.registerLibraryClass("bilab","protein");
    NamespaceScope.registerLibraryClass("bilab","alignment");
    NamespaceScope.registerLibraryClass("bilab","molecule");
    NamespaceScope.registerLibraryClass("bilab","seqdb");
    NamespaceScope.registerLibraryClass("bilab","picture");
    NamespaceScope.registerLibraryClass("bilab","tree");
    NamespaceScope.registerLibraryClass("bilab","Notify");
    NamespaceScope.registerLibraryClass("bilab","Doc");
    NamespaceScope.registerLibraryClass("bilab","Summary");
    NamespaceScope.registerLibraryClass("bilab","Sophistication");
    NamespaceScope.registerLibraryClass("bilab","Util");
    NamespaceScope.registerLibraryClass("bilab","Emboss");
    NamespaceScope.registerLibraryClass("bilab","ExternalApps");
    NamespaceScope.registerLibraryClass("bilab","INotifier");
    NamespaceScope.registerLibraryClass("bilab","IAnnotated");
    
    
    globalScope.addUsingNamespace("bilab"); // make java bilab package available

    
    ResourceManager rm = getResourceManager(); // alias
    
    // register some value viewers
    // NB: register viewed subclasses before their more generic supers
    Notify.logInfo(this,"Registering typed viewers");
    rm.registerViewer(new TypeSpec(DNA.class), new TypeSpec(ArtemisViewer.class)); 
    rm.registerViewer(new TypeSpec(RNA.class), new TypeSpec(ArtemisViewer.class)); 
    rm.registerViewer(new TypeSpec(protein.class), new TypeSpec(SeqStringViewer.class)); 
    
    rm.registerViewer(new TypeSpec(molecule.class), new TypeSpec(JMolViewer.class)); // molecule viewer

    rm.registerViewer(new TypeSpec(alignment.class), new TypeSpec(JalViewAlignmentViewer.class)); // multiple alignment viewer
    
    rm.registerViewer(new TypeSpec(picture.class), new TypeSpec(PictureViewer.class)); 
    rm.registerViewer(new TypeSpec(java.net.URL.class), new TypeSpec(HTMLViewer.class));
    rm.registerViewer(new TypeSpec(tree.class), new TypeSpec(TreeViewer.class));

    
    
    Notify.logInfo(this,"Registering resource types");

    // register resource types
    rm.registerResourceType("TEXT", "Unicode UTF-8 text", "txt");
    rm.registerResourceType("HTML", "Hyper-Text Markup Language document","html","htm");
    
    rm.registerResourceType("PNG", "Portable Network Graphics (PNG) bitmap", "png");
    rm.registerResourceType("JPG", "Joint Photographic Experts Group (JPEG) bitmap", "jpg", "jpeg");
    rm.registerResourceType("GIF", "Compuserve Graphics Interchange Format (GIF) bitmap", "gif");
    rm.registerResourceType("BMP", "Windows Bitmap image (BMP)", "bmp");

    rm.registerResourceType("Postscript", "Postscript program drawing", "ps", "eps");

    rm.registerResourceType("pdb", "Protein Data Bank", "pdb", "ent");
    rm.registerResourceType("mol", "Molecular Design Limited's (MDL) Mol file", "mol", "mdl");
    rm.registerResourceType("pqs", "PQS format", "pqs");
    rm.registerResourceType("sdf", "MDL ISIS SDF format", "sdf", "sd");
    rm.registerResourceType("xyz", "Minnesota Supercomputer Center's (MSC) XYZ (XMol) format", "xyz");
    
    rm.registerResourceType("EMBL", "EMBL Nucleotide Sequence Database (EMBL-Bank)", "embl");
    rm.registerResourceType("SwissProt" , "European Bioinformatics Institute (EBI) Swiss-Prot protein database", "");
    rm.registerResourceType("GenBank", "GenBank NCBI/NIH nucleotide sequence databse", "gb");
    rm.registerResourceType("GenPept", "GenPept NCBI/NIH protein sequence database", "");
    
    rm.registerResourceType("CT","naview RNA secondary structure format","ct");
    rm.registerResourceType("ABI", "ABI automated chromatagraph sequencer trace format", "abi");

    rm.registerResourceType("FASTA", "Pearson/FASTA DNA/protein sequence", "fa", "fsa", "fasta", "fna");
    rm.registerResourceType("BLAST", "BLAST similarity search results", "blast");
    
    rm.registerResourceType("CLUSTALW", "CLUSTALW Multiple sequence alignment","aln");
    rm.registerResourceType("MSF", "Pileup/GCG Multiple sequence alignment","msf");
    rm.registerResourceType("PFAM", "PFAM multiple alignment", "");
    rm.registerResourceType("BLC", "AMPS multiple alignment", "");
    
    rm.registerResourceType("MEV", "TIGR MultiExperimentViewer Microarray data", "mev");
    rm.registerResourceType("Genepix", "Genepix Microarray data", "grp");
    rm.registerResourceType("Affymetrix", "Affymetrix Microarray data", "txt");
    
    rm.registerResourceType("Newick", "Newick generic tree format", "newick");
    rm.registerResourceType("list(Newick)", "a list of Newick format trees", "");
    rm.registerResourceType("PhylipMultiSeq", "sequence set in Phylip linear format","");
    
    
    Notify.logInfo(this,"Registering resource importers");

    // register resource importers 
    // NB: register subclasses before their more generic supers
    rm.registerResourceIOProvider(new TypeSpec(MoleculeImpl.class));
    rm.registerResourceIOProvider(new TypeSpec(seq.class));
    rm.registerResourceIOProvider(new TypeSpec(alignment.class));
    rm.registerResourceIOProvider(new TypeSpec(picture.class));
    rm.registerResourceIOProvider(new TypeSpec(tree.class));
    
    initializePython();

    
    
    // execute bilab.sg core library
    try {
      Notify.userInfo(this,"executing bilab.sg library");
      InputStream srcStream = rm.findResource("libs/bilab.sg").openStream();
      executor.executeSource(srcStream,"bilab.sg");
      srcStream.close();
    } catch (Throwable e) {
      Notify.userWarning(this,"error executing bilab.sg library:"+e);
    }
    
    globalScope.addUsingNamespace("bilab.lib");

    
    // test!!!!!!!!!!!
    //OutputStream configResource = rm.createResourceStream("/U:/dev/GTL/win/BiLabRCP/BiLab/resources/testconfig.xml");
    //getAddOnManager().writeTestConfig( configResource );
    //configResource.close();
    Notify.logInfo(this,"Reading add-on configurations");
    
    String filename=null;
    try {
      filename = "emboss.xac";
      getAddOnManager().processConfiguration( rm.findResourceStream(filename) );
      globalScope.addUsingNamespace("bilab.emboss");

      filename = "phylip.xac";
      getAddOnManager().processConfiguration( rm.findResourceStream(filename) );
      globalScope.addUsingNamespace("bilab.phylip");
      
    } catch (Exception e) {
      Notify.devWarning(this,"Error reading add-on config file '"+filename+"' - "+e.getMessage());
      e.printStackTrace();
    }


    
    // execute sample.sg
    try {
      Notify.userInfo(this,"executing sample.sg");
      InputStream srcStream = rm.findResource("libs/sample.sg").openStream();
      executor.executeSource(srcStream, "sample.sg");
      srcStream.close();
    } catch (Throwable e) {
      Notify.userWarning(this,"error executing sample.sg:"+e);
    }
    
    
    
  }

  
  
  protected void loadLibrary(String jarName) throws IOException
  {
    NamespaceScope.loadLibrary(Util.toNativePathSeparator(getResourceManager().resourceURLToFilename(getResourceManager().findResource("libs/"+jarName))));
  }
  
  
  
  protected void initializePython()
  {
    try {
      ResourceManager rm = getResourceManager();
      Notify.devInfo(this,"Instantiating Python interpreter [Jython]");
      String pythonHome = rm.resourceURLToFilename( rm.findResource("libs/jython") );
      Properties pythonProps = new Properties();
      pythonProps.setProperty("python.home",pythonHome);
      pythonProps.setProperty("python.path",pythonHome);
      pythonProps.setProperty("python.cachedir","cachedir");
    
      PythonInterpreter.initialize(System.getProperties(), pythonProps, new String[0]);
      python = new PythonInterpreter();
      
      //python.setOut(...); /!!! redirect to bilab console
      //python.setErr(...);
      
    } catch (IOException e) {
      Notify.logError(this,"unable to instantiate python interpreter");
    }
  }
  
  
  

  
  
  /**
   * This method is called when the plug-in is stopped
   */
  public void stop(BundleContext context) throws Exception
  {
    python.cleanup();
    
    super.stop(context);
    plugin = null;
  }


  
  


  public NamespaceScope getGlobalScope()
  {
    return globalScope;
  }

  // scigol global napespace
  protected NamespaceScope globalScope;
  protected ISourceExecutor executor;

  


}
