/* CorbaApplet.java
 *
 * created: Mon Feb  8 1999
 *
 * This file is part of Artemis
 * 
 * Copyright (C) 1998,1999,2000  Genome Research Limited
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /nfs/disk222/yeastpub/Repository/powmap/CorbaApplet.java,v 1.14 2000/01/24 17:04:11 kmr Exp $
 **/

import diana.*;
import diana.components.*;
import diana.sequence.*;

import uk.ac.sanger.pathogens.*;

import uk.ac.sanger.pathogens.embl.LocationParseException;
import uk.ac.sanger.pathogens.embl.InvalidKeyException;
import uk.ac.sanger.pathogens.embl.EntryInformation;
import uk.ac.sanger.pathogens.embl.QualifierInfoVector;
import uk.ac.sanger.pathogens.embl.QualifierInfoException;
import uk.ac.sanger.pathogens.embl.InvalidRelationException;

import nsdb.EmblSeq;
import type.NoResult;
import nsdb.EmblPackage.Superceded;

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;

/**
 *  This applet will retrieve an embl entry for a corba server and then
 *  display it using a diana.components.EntryEdit object.
 *
 *  @author Kim Rutherford
 *  @version $Id: CorbaApplet.java,v 1.14 2000/01/24 17:04:11 kmr Exp $
 **/

public class CorbaApplet extends java.applet.Applet {
  /**
   *  Initialise this CorbaApplet applet.
   **/
  public void init () {
    Diana.setIsApplet (true);

    final Font font = Diana.getOptions ().getFont ();

    setFont (font);
    
    final StringVector extra_keys =
      Diana.getOptions ().getOptionValues ("extra_keys");

    try {
      final QualifierInfoVector extra_qualifiers =
        Diana.getOptions ().getExtraQualifiers ();

      final InputStream feature_keys_stream =
        Diana.getFileFromJar ("etc/feature_keys");

      final InputStream qualifier_types_stream =
        Diana.getFileFromJar ("etc/qualifier_types");
 
      EntryInformation.initialise (feature_keys_stream,
                                   qualifier_types_stream,
                                   extra_keys,
                                   extra_qualifiers);
    } catch (IOException e) {
      final String message =
        "could not initialise the embl package: " + e.getMessage ();

      System.out.println (message);
      new MessageFrame (message);
      return;
    } catch (QualifierInfoException e) {
      final String message =
        "could not initialise the embl package: " + e.getMessage ();

      System.out.println (message);
      new MessageFrame (message);
      return;
    }

    setLayout (new BorderLayout ());

    final Label label = new Label ("Enter an accession number:");
    add (label, "North");

    final Panel centre_panel = new Panel ();
    add (centre_panel, "Center");

    final Panel text_field_panel = new Panel ();
    centre_panel.add (text_field_panel);


    text_field = new TextField (20);
    centre_panel.add (text_field, "North");
  
    final Button go = new Button ("Go");
    centre_panel.add (go);

    go.addActionListener (new ActionListener () {
      public void actionPerformed(ActionEvent e) {
        getEntry ();
      }
    });

    errors = new Label ("");
    add (errors, "South");

    text_field.addKeyListener (new KeyAdapter () {
      public void keyTyped(final KeyEvent e) {
//        errors.setText ("key: " + e.getKeyChar ());

        if (e.getKeyChar () == '\n') {
          if (text_field.getText () == null ||
              text_field.getText ().length () == 0) {
            return;
          }

          getEntry ();
        }
      }
    });
  }

  /**
   *  Read the accession number of an EMBL entry from the text_field and then
   *  try to get it. 
   **/
  private void getEntry () {
    errors.setText ("trying to open: " + text_field.getText ());
          
    final uk.ac.sanger.pathogens.embl.Entry new_embl_entry =
      readEntry (text_field.getText ());

    if (new_embl_entry == null) {
      errors.setText ("could not open: " + text_field.getText ());
      return;
    }

    final Bases embl_bases = new Bases (new_embl_entry.getSequence ());
      
    final EntryGroup entry_group = new SimpleEntryGroup (embl_bases);

    try {
      final Entry new_entry =
        new Entry (entry_group.getBases (), new_embl_entry);

      entry_group.add (new_entry);
    } catch (OutOfRangeException _) {
      new MessageFrame ("load failed: there is an out of " +
                        "range feature location");
    }

    final EntryEdit entry_edit = new EntryEdit (entry_group);

    // this call is done so that the EntryEdit components can be closed
    // later
    Diana.addEntryEdit (entry_edit);

    entry_edit.setSize (700,600);
    entry_edit.validate ();

    errors.setText ("");

    entry_edit.setVisible (true);
  }

  /**
   *  Read and return an embl.Entry object from the server.
   *  @param accession_number The accession number of the entry to read from
   *    the server.  It must be in the same directory as the java code.
   **/
  private uk.ac.sanger.pathogens.embl.Entry readEntry (final String
                                                         accession_number) {
    final org.omg.CORBA.ORB orb =
      org.omg.CORBA.ORB.init (new String [0], new java.util.Properties ());

    final org.omg.CORBA.Object obj;

    try {
      obj = orb.string_to_object (getIOR ());
    } catch (IOException e) {
      final String message =
        "Error while reading EMBL IOR: " + e.getMessage ();
      System.err.println (message);
      errors.setText (message);
      return null;
    }
    
    final nsdb.Embl corba_handle = nsdb.EmblHelper.narrow (obj);

    if (corba_handle == null) {
      final String message = "Failed to get an object from Corba/EMBL";
      System.err.println (message);
      errors.setText (message);
      return null;
    }
          
    try {
      final EmblSeq embl_seq = corba_handle.getEmblSeq (accession_number);
      
      return new uk.ac.sanger.pathogens.embl.CorbaEntry (embl_seq);
    } catch (NoResult e) {
      final String message =
        "Database query failed while getting accession number: " +
        accession_number;
      System.err.println (message);
      errors.setText (message);
    } catch (Superceded e) {
      //  Superceded is used by getEmblSeq method if accession number
      //  doesn't exist anymore because it was merged or split
      final String message =
        "This accession number has been superceded: " + accession_number;
      System.err.println (message);
      errors.setText (message);
    } catch (LocationParseException e) {
      final String message =
        "Unexpected error while accessing " + accession_number + ": " + e;
      System.err.println (message);
      errors.setText (message);
    } catch (InvalidKeyException e) {
      final String message =
        "Unexpected error while accessing " + accession_number + ": " + e;
      System.err.println (message);
      errors.setText (message);
    }
//      } catch (java.lang.Throwable e) {
//        final String message =
//          "Unexpected error while accessing " + accession_number + ": " + e;
//        errors.setText (message);
//        new MessageDialog (Diana.this, message);
//        return;
//      }

    return null;
  }

  /**
   *  Finds and returns a stringified object reference (IOR).
   *
   *  @return The stringified IOR.
   *  @exception IOException Thrown if an error occurs while reading.
   **/
  private String getIOR ()
      throws IOException {
    try {
      //  get URL of IOR
      URL url = new URL (default_ior_url);
      BufferedReader in =
        new BufferedReader (new InputStreamReader (url.openStream()));
      return in.readLine();
    } catch (MalformedURLException e) {
      throw new Error ("internal error - unexpected MalformedURLException: " +
                       e.getMessage ());
    }
  }

  /**
   *  The default place to look for the IOR for the corba server.
   **/
  static private final String default_ior_url =
    "http://www.sanger.ac.uk/Users/kmr/ior";

  /**
   *  A label for status and error messages.
   **/
  private Label errors;

  /**
   *  The user will type the accession number into this field.
   **/
  private TextField text_field;
}
