#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/un.h>
#include <netdb.h>
#include <X11/keysym.h>

#include "OXIrc.h"
#include "OXChannel.h"

//----------------------------------------------------------------------

OLayoutHints  * leftexpandylayout =
    new OLayoutHints(LHINTS_LEFT | LHINTS_EXPAND_Y,1,1,1,1);

OLayoutHints  * topexpandxlayout =
    new OLayoutHints(LHINTS_TOP | LHINTS_EXPAND_X,1,1,1,1);

OLayoutHints  * expandxexpandylayout =
    new OLayoutHints(LHINTS_EXPAND_Y | LHINTS_EXPAND_X,1,1,1,1);

OXIrc::OXIrc(const OXWindow *p, char * nick, char * server, int port) :
  OXMainFrame(p, 400, 300) {
  char tmp[TCP_BUFFER_LENGTH];

  channels = NULL;

  SetLayoutManager(new OVerticalLayout(this));

  _channelentry = new OXMyTextEntry(this, _channel = new OTextBuffer(100));
  _channelentry->ChangeOptions(FIXED_WIDTH | SUNKEN_FRAME | DOUBLE_BORDER);
  AddFrame(_channelentry, topexpandxlayout);

  _logw = new OXView(this, _log = new OTextDoc(), 10, 10, MAIN_FRAME);
  _logw->SetScrollOptions(FORCE_VSCROLL | NO_HSCROLL);
  AddFrame(_logw, expandxexpandylayout);

  MapSubwindows();
  SetWindowName("fOXIrc");

  Resize(500,300);

  strcpy(_nick, nick);
  strcpy(_server, server);
  _port = port;

  Connect(server, port);
  sprintf(tmp, "NICK %s\nUSER %s %s %s :%s\n",
             _nick, getenv("USER"), getenv("HOSTNAME"),
             _server, getenv("LOGNAME")); 
  Send(tmp);
  Log("Connecting to server");
  Log(" ");

  _timer = new OTimer(this, 300);
}

OXIrc::~OXIrc() {
}

void OXIrc::Log(char * message) {
  Log(message, "white");
}

void OXIrc::Log(char * message, char * color) {
  OLineDoc * l = new OLineDoc();
  l->SetCanvas(_log->_style_server);
  l->SetColor(color);
  l->Fill(message);
  _log->AddLine(l);
  _logw->ScrollDown();
}

OXChannel * OXIrc::GetChannel(char * channel) {
  OXChannel * ch;

  if (channels)
    ch = channels->GetChannel(channel);
  else
    ch = channels = new OXChannel(_client->GetRoot(), this, channel);
  return ch;
}


void OXIrc::ProcessNickList(char * channel, char * nicklist) {
  GetChannel(channel)->NickList(nicklist);
}

void OXIrc::ProcessJoin(char * channel, char * nick) {
 GetChannel(channel)->NickJoin(nick);
}

void OXIrc::ProcessPart(char * channel, char * nick) {
 GetChannel(channel)->NickLeave(nick);
}

void OXIrc::ProcessNick(char * old_nick /* :*] */, char * new_nick) {
  for(OXChannel * i = channels; i; i= i->_next)
    i->NickChange(old_nick, new_nick); 
}

void OXIrc::ProcessQuit(char * nick) {
  for(OXChannel * i = channels; i; i= i->_next)
    i->NickLeave(nick); 
}

void OXIrc::ProcessMsg(char * channel, char * nick, char * msg, int mode) {
  if (!strcasecmp(channel, _nick)) {
    GetChannel(nick)->Say(nick, msg, mode);
  } else {
    GetChannel(channel)->Say(nick, msg, mode);
  }
}

int OXIrc::ProcessMessage(long msg, long parm1, long parm2) {
  char tmp[100];
  switch(GET_MSG(msg)) {
    case XC_TEXTENTRY:
      switch(GET_SUBMSG(msg)) {
        case TE_TEXTCHANGED:
          switch(parm2) {
            case XK_Return:
              sprintf(tmp, "JOIN %s\nMODE %s\n",
                          _channel->GetString(), _channel->GetString());
              Send(tmp);
              break;
          }
          break;
      }
    break;
  }
  return True;
}

int OXIrc::HandleTimer(OTimer *t)
{
  _timer = new OTimer(this, 300);
  Receive();
  return True;
}
