package telnet;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
import ssh.*;

/* This file is part of "Telnet Floyd".
 *
 * (c) Radek Polak 2003-2004. All Rights Reserved.
 *
 * Please visit project homepage at http://phoenix.inf.upol.cz/~polakr
 *
 * --LICENSE NOTICE--
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 * --LICENSE NOTICE--
 *
 */

/**
 * Main class for whole application. Here are all important variables defined
 * as public static members, so that they can be easily accessed. See also
 * method run, that handles main telnet loop.
 */

public class Telnet
    extends MIDlet
    implements Runnable {

  private static Telnet instance;

  /** handles with data from telnet and with data from user */
  public static vt320 emulation;
  /** user interface */
  public static MidletTerminal terminal;


  public static Console console=new Console();

  /**
   * We will collect here data for writing. Data will be sent when nothing is
   * in input stream, otherwise midlet hung up.
   * @see #run
   */
  public static byte[] output = new byte[16];  // this will grow if needed

  /**
   * Number of bytes to be written, from output array, because it has fixed
   * lenght.
   */
  public static int outputCount = 0;

  public static SshIO sshIO = null;

  public static int traffic = 0;

  /** Time to sleep between checks for new input from connection */
  public static int sleepTime = 1000;

  /** After this count of cycles without communication on connection we will send something just to keep connection alive */
  public static int keepAliveCycles = 300; // 5 minutes for sleepTime=1000

  /**
   * Holds the socket connetion object (from the Generic Connection
   * Framework) that is the basis of this connection.
   */
  public static StreamConnection socket;

  /**
   * Holds the InputStream associated with the socket.
   */
  private static DataInputStream in;

  /**
   * Holds the OutputStream associated with the socket.
   */
  public static DataOutputStream out;

  public static String host;

  public static Thread reader;

  public static boolean useColors;

  /** Constructor */
  public Telnet() {

//    System.out.println( Action.EXIT_APP.hashCode() );
    instance = this;
    useColors = getDisplay().isColor();

    // we now create a new terminal that is used for the system
    // if you want to configure it please refer to the api docs
    emulation = new vt320();
    terminal = new MidletTerminal(emulation);
    sshIO = new SshIO();
  }

  /** Main method */
  public void startApp() {
    setDisplay( (Displayable) terminal);
    reader = new Thread( this );
  }
  /** Handle pausing the MIDlet */
  public void pauseApp() {
  }

  /** Handle destroying the MIDlet */
  public void destroyApp(boolean unconditional) {
  }

  /** Quit the MIDlet */
  public static void quitApp() {
    instance.destroyApp(true);
    instance.notifyDestroyed();
    instance = null;
  }

  public static void setDisplay(Displayable display) {
    instance.getDisplay().setCurrent(display);
  }

  public Display getDisplay() {
    return Display.getDisplay(this);
  }

  /**
   * Continuously read from remote host and display the data on screen.
   */
  public void run() {

    int n;
    int noInputCycles = 0;


    // Connect
    try
    {
      emulation.putString("Connecting...");
      terminal.redraw();
      socket = (StreamConnection) Connector.open("socket://"+host+":22",
                                                 Connector.READ_WRITE, false);
      in = socket.openDataInputStream();
      out = socket.openDataOutputStream();
      emulation.putString("OK");
    }
    catch( Exception e )
    {
      emulation.putString("FAILED");
    }
    emulation.putString("\n\r");
    terminal.redraw();

    // Main loop
    try {
      for(;;) {

        n = in.available();

        if( n <= 0 )
        {
          if( outputCount > 0 )  // Writing
          {
            traffic += outputCount;
            out.write(output, 0, outputCount);
            outputCount = 0;
          }
          else  // Sleeping
          {
            Thread.sleep(sleepTime);
            if( noInputCycles++ > keepAliveCycles )
            {
              emulation.keyTyped( 0, 'a', 0 ); // BAD HACK - SHOULD SEND AYA...
              emulation.keyPressed( 8, '\b', 0 );
              noInputCycles=0;
            }
          }
        }
        else // Reading
        {
          byte[] b = new byte[n];
          in.read( b, 0, n );
          byte[] tmp = new byte[n];
          System.arraycopy(b, 0, tmp, 0, n);
          byte[] buffer = sshIO.handleSSH(tmp);
          if(buffer != null && buffer.length > 0)
          {
            if (n > 0) {
              try {
                emulation.putString(new String(buffer));
                terminal.redraw();
              }
              catch (Exception e) {}
            }
          }
           noInputCycles = 0;
        }
      } // while( connected )
    }
    catch (Exception e) {
      console.append( e.getMessage());
    }
  }
}
