import java.io.*;
import java.util.*;
import com.motorola.lwt.*; //sorry 'bout that
import javax.microedition.io.*;
import javax.microedition.rms.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Display;



/*
Hi there boys and girls, today we'll play a fun
game called "Don't screw Vidar over". The way you
play is you give Vidar a spot on the credits for
whatever program you make using this source code!

After that, feel free to express your love for j2me,
open source and the author by sending mail to
vidar at vidnet dot homelinux dot net. If you don't, 
I'll stop commenting the source code and obfuscate 
the classes like everyone else does. And we don't 
want that, now do we?


Sounds fun, yeah?
Enjoy!
Vidar

Meet me on irc, #java on dalnet. 
I'm koala_man.
*/


public class A008Chat extends MIDlet implements ComponentListener, Runnable {
    protected boolean config=true;
    protected ComponentScreen cs;
    protected TextArea ta;
    protected TextField tf, tfnick, tfchannel, tfhost;
    protected Button tb;
    protected Font mf;
    protected StreamConnection sc;
    protected InputStream in;
    protected OutputStream out;
    protected String host, nick, channel;


    public A008Chat() throws Exception {
        //We'll use a small font for more space.
        mf=(Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_SMALL));

        //Now, let's load our setup.
        try {
            RecordStore rs=RecordStore.openRecordStore("a008chat", false);
            RecordEnumeration re=rs.enumerateRecords(null,null,true);
            host=new String(rs.getRecord(re.nextRecordId()));
            nick=new String(rs.getRecord(re.nextRecordId()));
            channel=new String(rs.getRecord(re.nextRecordId()));
        } catch(Exception e) {
            //Ow, malformed or nonexistant setup! Default.
            host="liberty.dal.net:6667";
            nick="Moron"+((new Random().nextInt())%1000);
            channel="#A008Chat";
        }
        setupConfig();
    }

    //set up the config components
    protected void setupConfig() {
        config=true;
        ta=null;
        tf=null;
        cs=new ComponentScreen();
        tfhost=new TextField(host,24);
        tfnick=new TextField(nick,24);
        tfchannel=new TextField(channel,24);
        tb=new Button("Connect!");
        tfhost.setFont(mf);
        tfnick.setFont(mf);
        tfchannel.setFont(mf);
        tb.setFont(mf);
        tb.setComponentListener(this);
        cs.add(tfhost);
        cs.add(tfnick);
        cs.add(tfchannel);
        cs.add(tb);
    }

    //set up the chatting interface.
    protected void setupChat() {
        config=false;
        tfhost=null;
        tfnick=null;
        tfchannel=null;
        cs=new ComponentScreen();
        ta=new TextArea("Welcome\nA008Chat\nVidar Holen\n",6,30);
        tf=new TextField("",15);
        tb=new Button("Send");
        tb.setComponentListener(this);
        ta.setFont(mf);
        tf.setFont(mf);
        tb.setFont(mf);
        cs.add(ta);
        cs.add(tf);
        cs.add(tb);
    }

    public void run() {
        try {
            sc=(StreamConnection) Connector.open("socket://"+host);
            in=sc.openInputStream();
            out=sc.openOutputStream();

            //Here's how we connect to an IRC server.
            send("USER A008 0 * :A008Chat by Vidar Holen");
            send("NICK "+nick);
            send("JOIN "+channel);

            String nick, msg, s;

            //yeah, exit conditions suck.
            while(true) {
                s=readLine();
                try {
                    //received irc message (rfc1459):
                    //:nick!user@address ACTION target :Message
                    //:koala_man!vidar@21.10.242.53 PRIVMSG #java :Hi all

                    nick=s.substring(1,s.indexOf("!"));
                    msg=s.substring(s.indexOf(":",1)+1);
                    s=s.substring(s.indexOf(" ")+1);
                    if(s.startsWith("PING")) send("PONG "+nick); //have to return pings
                    s=s.substring(0,s.indexOf(" "));
                    if(s.equals("PRIVMSG")) putText(nick+": "+msg); else //say something
                            if(s.equals("JOIN")) putText(nick+" joined."); else  //someone join
                                    if(s.equals("PART")) putText(nick+" left."); else //someone left
                                if(s.equals("QUIT")) putText(nick+" quit: "+msg); //someone disconnected
                } catch(StringIndexOutOfBoundsException e) { /* server messages and stuff */ }
            }

        } catch(Exception e) { putText(e.getMessage()); }
    }

    protected String readLine() throws IOException {
        StringBuffer b=new StringBuffer();
        int c;

        //No BufferedReader, but we'll manage.
        //We let \n be eol and we'll just skip all the \l's

        while((c=in.read())!='\n' && c!=-1) {
            if(c!=0x0A) b.append((char)c);
        }
        return b.toString();
    }

    //Simply send the string s followed by a newline
    protected void send(String s) {
        try {
            s=s+"\n";
            out.write(s.getBytes());
        } catch(IOException e) {
            putText(e.getMessage());
        }
    }

    //MIDlet methods
    protected void startApp() {
        Display.getDisplay(this).setCurrent(cs);
    }
    protected void destroyApp(boolean b){}
    protected void pauseApp() {}


    public void processComponentEvent(Object o, int i) {
        if(!config) { //we're in chat mode
            if(tf.getText().length()>0) {
                putText("KG> "+tf.getText());
                if(tf.getText().startsWith("/")) send(tf.getText().substring(1)); //a command!
                else send("PRIVMSG "+channel+" :"+tf.getText()); //say something
                tf.setText("");
                //if we push the button when there's no text to send,
                //remove the first line for visibility.
            } else ta.setText(ta.getText().substring(ta.getText().indexOf("\n")+1));
        } else { //we're in the connect dialog phase
            host=tfhost.getText();
            nick=tfnick.getText();
            channel=tfchannel.getText();
            //Delete any old data and add our new settings.
            try {
                try {
                    RecordStore.deleteRecordStore("a008chat");
                } catch(RecordStoreNotFoundException e) {}
                RecordStore rs=RecordStore.openRecordStore("a008chat", true);
                rs.addRecord(tfhost.getText().getBytes(),0,tfhost.getText().length());
                rs.addRecord(tfnick.getText().getBytes(),0,tfnick.getText().length());
                rs.addRecord(tfchannel.getText().getBytes(),0,tfchannel.getText().length());
                setupChat();
                Display.getDisplay(this).setCurrent(cs);
                new Thread(this).start();
            } catch(Exception e) {/*we're screwed*/}
        }
    }

    public void putText(String s) {
        String t=ta.getText();
        t=t.substring(t.indexOf("\n")+1);
        t=t+"\n"+s;
        ta.setText(t);
    }

}

