import keggapi.*;

import uk.ac.ebi.chebi.webapps.chebiWS.client.ChebiWebServiceClient;
import uk.ac.ebi.chebi.webapps.chebiWS.model.*;

import java.io.*;
import java.net.*;
import java.util.*;
import iotools.*;

// -------------------------------------------------------------
// get enzyme-related information from KEGG given an EC #
// -------------------------------------------------------------

public class EnzymeKEGG
{
  public EnzymeKEGG() {}

  public void getTerms()
  {
    try
    {

      // --- step 1: start creating a few objects needed for download
      URL            u;
      InputStream    is = null;
      BufferedReader dis;
      String         s;

      // --- to connect to the local PubChem Extra DB
      PubChemLocal pubchemLocal = new PubChemLocal();

      // --- create chebiWS client
      ChebiWebServiceClient client = new ChebiWebServiceClient();

      KEGGLocator  locator = new KEGGLocator();
      KEGGPortType serv    = locator.getKEGGPort();

      // --- open INPUT file

      Configuration config = new Configuration();

      String dir_name = config.path() + "\\input\\";

      String EC_file = dir_name + config.input_EC();
      EasyReader EC_in   = new EasyReader(EC_file);

      // --- open OUTPUT files

      dir_name = config.path() + "\\output\\KEGG\\";

      String     enzyme_file = dir_name + config.enzyme();
      FileWriter enzyme_out  = new FileWriter(enzyme_file);

      String     compound_file = dir_name + config.compound();
      FileWriter compound_out  = new FileWriter(compound_file);

      String     gene_file = dir_name + config.gene();
      FileWriter gene_out  = new FileWriter(gene_file);

      String     enzyme_name_file = dir_name + config.enzyme_name();
      FileWriter enzyme_name_out  = new FileWriter(enzyme_name_file);

      String     compound_name_file = dir_name + config.compound_name();
      FileWriter compound_name_out  = new FileWriter(compound_name_file);

      String     gene_name_file = dir_name + config.gene_name();
      FileWriter gene_name_out  = new FileWriter(gene_name_file);

      String     enzyme2compound_file = dir_name + config.enzyme2compound();
      FileWriter enzyme2compound_out  = new FileWriter(enzyme2compound_file);

      String     enzyme2gene_file = dir_name + config.enzyme2gene();
      FileWriter enzyme2gene_out  = new FileWriter(enzyme2gene_file);


      // --- for each enzyme
      while (!EC_in.eof())
      {
        // --- read an EC number
        String enzyme = EC_in.readString();
        String enzyme_line = enzyme;

        // --- get the synonyms for the given enzyme
        String title = serv.btit("EC " + enzyme).trim() + ";";

        int b, e = 0;

        while ((b = title.indexOf(' ', e)) >= 0)
        {
          b++; e = title.indexOf(';', b);

          String name = title.substring(b, e);
          String line = enzyme + "\t" + name + "\n";
          System.out.print(line);
          enzyme_name_out.write(line);
        }


        // --- get the related compounds, genes and PMIDs for 
        //     the given enzyme
        String search_base = "http://www.genome.jp/dbget-bin/www_bget?";

        String url = search_base + "enzyme+" + enzyme;

        u   = new URL(url);
        is  = u.openStream();
        dis = new BufferedReader(new InputStreamReader(is));

        List<String> compoundBag = new ArrayList<String>();
        List<String>      sceBag = new ArrayList<String>();
        List<String>  medlineBag = new ArrayList<String>();

        while ( (s = dis.readLine()) != null )
        {
          b = 0; e = 0;
          String href = "<a href=\"/dbget-bin/www_bget?";
          int  offset = href.length();

          while (b >= 0)
          {
            b = s.indexOf(href, e);

            if (b >= 0)
            {
              b += offset;
              e  = s.indexOf("\"", b);

              String xref = s.substring(b, e);

              int plus = xref.indexOf('+');

              String db = xref.substring(0, plus++);
              String id = xref.substring(plus);

              if (db.compareTo("compound") == 0)
                {if (!(compoundBag.contains(id))) compoundBag.add(id);}
              else if (db.compareTo("sce") == 0)
                {if (!(sceBag.contains(id)))      sceBag.add(id);     }
              else if (db.compareTo("medline") == 0)
                {if (!(medlineBag.contains(id)))  medlineBag.add(id); }
            }
          }
        }


        // --- for each related compound

        for (Iterator<String> iter = compoundBag.iterator(); iter.hasNext(); )
        {
          String compound      = iter.next();
          String sid           = "NULL";
          String chebi         = "NULL";

          enzyme2compound_out.write(enzyme + "\t" + compound + "\n");

          // --- get the compound names from KEGG
          title = serv.btit("cpd:" + compound).trim() + ";";

          b = 0; e = 0;

          while ((b = title.indexOf(' ', e)) >= 0)
          {
            b++; e = title.indexOf(';', b);

            String name = title.substring(b, e);
            String line = compound + "\t" + name + "\n";
            System.out.print(line);
            compound_name_out.write(line);
          }


          // --- get xrefs to PubChem & ChEBI
          url = search_base + "compound+" + compound;

          u   = new URL(url);
          is  = u.openStream();
          dis = new BufferedReader(new InputStreamReader(is));

          while ( (s = dis.readLine()) != null )
          {
            int offset;
            String source;

            source = "PubChem: <a href=\"http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?sid=";
            offset = source.length();

            if ( (b = s.indexOf(source)) >= 0)
            {
              b += offset;
              e  = s.indexOf("\"", b);
              sid = s.substring(b, e);
            }

            source = "ChEBI: <a href=\"http://www.ebi.ac.uk/chebi/searchId.do?chebiId=";
            offset = source.length();

            if ( (b = s.indexOf(source)) >= 0)
            {
              b += offset;
              e  = s.indexOf("\"", b);
              chebi = s.substring(b, e);
            }
          }

          String compound_line = compound + "\t" + sid + "\t" + chebi + "\n";
          compound_out.write(compound_line);


          // --- get the compound names from PubChem substance
/* RUBBISH NAMES - commented out for the time being
 *         if (sid.compareTo("NULL") != 0)
 *         {
 *           List<String> synonyms = pubchemLocal.sid2syn((new Integer(sid)).intValue());
 *
 *           for (Iterator<String> i = synonyms.iterator(); i.hasNext(); )
 *           {
 *             String name = i.next();
 *             String line = compound + "\t" + name + "\n";
 *             System.out.print(line);
 *             compound_name_out.write(line);
 *           }
 *         }
 */

          // --- get the compound names from ChEBI
          if (chebi.compareTo("NULL") != 0)
          {
            Entity entity = client.getCompleteEntity(chebi);

            String name = entity.getChebiAsciiName();
            String line = compound + "\t" + name + "\n";
            System.out.print(line);
            compound_name_out.write(line);

            List<DataItem> synonyms = entity.getSynonyms();
            for (DataItem dataItem : synonyms)
            {
              name = dataItem.getData();
              line = compound + "\t" + name + "\n";
              System.out.print(line);
              compound_name_out.write(line);
            }
          }
        }



        // --- for each related gene

        for (Iterator<String> iter = sceBag.iterator(); iter.hasNext(); )
        {
          String gene = iter.next();
          String sgd  = "NULL";
          String mips = "NULL";

          enzyme2gene_out.write(enzyme + "\t" + gene + "\n");

          gene_name_out.write(gene + "\t" + gene + "\n");

          // --- get the gene names from KEGG
          title = serv.btit("sce:" + gene).trim() + ";";

          b = 0; e = 0;

          while ((b = title.indexOf(' ', e)) >= 0)
          {
            b++; e = title.indexOf(';', b);

            String name = title.substring(b, e);

            if (name.length() < 20)
            {
              String line = gene + "\t" + name + "\n";
              gene_name_out.write(line);
            }
          }


          // --- get xrefs to SGD & MIPS
          url = search_base + "sce+" + gene;

          u   = new URL(url);
          is  = u.openStream();
          dis = new BufferedReader(new InputStreamReader(is));

          while ( (s = dis.readLine()) != null )
          {
            int offset;
            String source;

            source = "SGD: <a href=\"http://genome-www4.stanford.edu/cgi-bin/SGD/locus.pl?locus=";
            offset = source.length();

            if ( (b = s.indexOf(source)) >= 0)
            {
              b += offset;
              e  = s.indexOf("\"", b);
              sgd = s.substring(b, e);
            }

            source = "MIPS: <a href=\"http://mips.gsf.de/genre/proj/yeast/searchEntryAction.do?text=";
            offset = source.length();

            if ( (b = s.indexOf(source)) >= 0)
            {
              b += offset;
              e  = s.indexOf("\"", b);
              mips = s.substring(b, e);
            }
          }

          String gene_line = gene + "\t" + sgd + "\t" + mips + "\n";
          gene_out.write(gene_line);


          // --- get gene names from SGD
          if (sgd.compareTo("NULL") != 0)
          {
            url = "http://db.yeastgenome.org/cgi-bin/reference/litGuide.pl?dbid=" + sgd;
            u   = new URL(url);
            is  = u.openStream();
            dis = new BufferedReader(new InputStreamReader(is));

            String target = "Other names published for ";
            int offset = target.length();

            while ( (s = dis.readLine()) != null )
            {
              if ( (b = s.indexOf(target)) >= 0)
              {
                b += offset;
                e  = s.indexOf('<', b);
                String synonyms = s.substring(b, e) + ", ";

                e = synonyms.indexOf(": ");
                String name = synonyms.substring(0, e);
                String line = gene + "\t" + name + "\n";
                gene_name_out.write(line);
                b = e+2;

                while ( (e = synonyms.indexOf(", ", b)) >=0 )
                {
                  name = synonyms.substring(b, e);
                  line = gene + "\t" + name + "\n";
                  gene_name_out.write(line);
                  b = e+2;
                }

                break;
              }
            }
          }
        }
      }

      enzyme_out.close();
      compound_out.close();
      gene_out.close();
      enzyme_name_out.close();
      compound_name_out.close();
      gene_name_out.close();
      enzyme2compound_out.close();
      enzyme2gene_out.close();
    }
    catch (ChebiWebServiceFault_Exception e) {System.err.println(e.getMessage());}
    catch (Exception e) {System.out.println(e.toString());}
  }


  int reactions(String compound)
  {
    try
    {
      KEGGLocator  locator = new KEGGLocator();
      KEGGPortType serv    = locator.getKEGGPort();

      // --- get the number of reactions linked to the compound

      String[] results = serv.get_reactions_by_compound("cpd:" + compound);
      
      return results.length;
    }
    catch (Exception e) {System.out.println(e.toString());}

    return -1;
  }


  String compoundName(String CID)
  {
    String name = CID;

    try
    {
      KEGGLocator  locator = new KEGGLocator();
      KEGGPortType serv    = locator.getKEGGPort();

      // --- get compound names from KEGG
      String title = serv.btit("cpd:" + CID).trim() + ";";

      int b = 0, e = 0;

      if ((b = title.indexOf(' ', e)) >= 0)
      {
        b++; e = title.indexOf(';', b);
        name = title.substring(b, e);
      }
    }
    catch (Exception e) {System.out.println(e.toString());}

    return name;
  }

}
