#include "ircd.h"
#include "socket.h"


int Parse(struct slist *lhead,Sock shead) 
{
    Users tuser;
    Channels tchan;
    struct slist head = *lhead;
    struct sockaddr_in peer;
    int peer_len;
    char command[128];
    char data[1024];
    char temp[1024];
    char *tmp;
    printf("Test: [%s][%i][%i]\n",shead->data,shead->id,shead->b);
    switch (shead->b) 
    {
        case 0:
        {
            printf("Case 0[%s]\n",shead->data);
            sprintf(command,"%s",strtok(shead->data," "));
            sprintf(data,"%s",strtok(NULL,"\n"));
            printf("Split: [%s][%s]\n",command,data);
            if (!strcasecmp(command, "NICK")) 
            {
                printf("NICK[%s]\n",command);
                printf("First: [%c]\n",data[0]);

                if (data[0] == ':') 
                { 
                    tmp = data; 
                    tmp++; 
                    sprintf(data,"%s",tmp); 
                }

                if (FindNick(head.users,data)) 
                {
                    SendSock(shead->socket,":%s 433 %s :Nickname is already in use.\n",
                            head.cf->servername,data);
                }
                else 
                {
                    printf("Nick Avail[%i]\n",shead->type);

                    if (shead->type == 0) 
                    {
                        printf("Adding User: [%i]\n",shead->socket);
                        shead->userinfo = AddUser(shead->id,shead->socket,data,&head.users);
                        NickList(head.users);
                        shead->type=1;
                    }

                    else if (shead->type >= 1) 
                    {
                        printf("Updating Nick: [%s][%i]\n",shead->userinfo->nick,shead->socket);
                        SendSock(shead->socket,":%s!%s@%s NICK :%s\n",
                                shead->userinfo->nick,shead->userinfo->ident,shead->userinfo->host,data);
                        sprintf(shead->userinfo->nick,data);

                        if (shead->type == 1) 
                        {
                            SendLogon(head,shead->userinfo->nick,shead->socket);
                            SendMotd(head,shead);
                            shead->type = 2;
                        }
                    }
                }
            }

            if (!strcasecmp(command,"USER")) 
            {
                sscanf(data,"%s %s %s :%s\n",shead->userinfo->ident,shead->userinfo->host,
                      shead->userinfo->server,shead->userinfo->name);
                tmp = shead->userinfo->host;
                tmp++;
                sprintf(shead->userinfo->host,"%s",strtok(tmp,"\""));
                tmp = shead->userinfo->server;
                tmp++;
                peer_len = sizeof(peer);

                if (getpeername(shead->socket,(struct sockaddr *)&peer,&peer_len) == -1) 
                {
                    perror("getpeername() failed");
                }

                printf("Peer IP Address: [%s]\n",inet_ntoa(peer.sin_addr));

                if (GetHost((char *)&shead->userinfo->host,inet_ntoa(peer.sin_addr))) 
                {
                    printf("GetHost Problem\n");
                    sprintf(shead->userinfo->host,"%s",inet_ntoa(peer.sin_addr));
                }
                printf("Peer Host Name: [%s]\n",shead->userinfo->host);
                sprintf(shead->userinfo->server,"%s",strtok(tmp,"\""));
                printf("Blah ident: [%s]\n",shead->userinfo->ident);

                if (shead->type == 1) 
                {
                    SendLogon(head,shead->userinfo->nick,shead->socket);
                    SendMotd(head,shead);
                    shead->type = 2;
                }
            }

            if (!strcasecmp(command,"MOTD")) 
            {
                SendMotd(head,shead);
            }

            if (!strcasecmp(command, "QUIT"))
            {
                printf("COMMAND: %s\nDATA\n", command,data);
                printf("USER: %s, has QUIT...\n", shead->userinfo->nick);
                tuser = FindNick(head.users,shead->userinfo->nick);
                if (tuser)
                {
                    printf("USER %s FOUND.\n", shead->userinfo->nick);
                } else {
                    printf("USER %s NOT FOUND\n", shead->userinfo->nick);
                }
                DeleteUser(tuser,shead->userinfo->sid);
                tuser = FindNick(head.users,shead->userinfo->nick);
                if (tuser)
                {
                    printf("USER %s FOUND.\n", shead->userinfo->nick);
                } else {
                    printf("USER %s NOT FOUND\n", shead->userinfo->nick);
                }

            }

            if (!strcasecmp(command,"PRIVMSG")) 
            {
                sprintf(command,"%s",strtok(data," "));

                if (command[0] == '#') 
                {
                    sprintf(temp,"%s",strtok(NULL,"\n"));
                    tchan = FindChannel(head.channels,command);
                    if (tchan) 
                    {
                        printf("Fucker is in a channel [%s][%s]\n",command,temp);
                        ShowChanPrivmsg(tchan,shead,head,temp);
                    }
                    else 
                    {
                        SendSock(shead->socket,":%s 401 %s %s :No such nick/channel\n",
                                head.cf->servername,shead->userinfo->nick,command);
                    }
                }
                else 
                {
                    tuser = FindNick(head.users,command);
                    if (tuser) 
                    {
                        SendSock(tuser->socket,":%s!%s@%s PRIVMSG %s %s\n",shead->userinfo->nick,
                                shead->userinfo->ident,shead->userinfo->host,command,strtok(NULL,"\n"));
                        printf("Priv: [%s][%i]\n",data,tuser->socket);
                    }
                    else 
                    {
                        SendSock(shead->socket,":%s 401 %s %s :No such nick/channel\n",head.cf->servername,
                                shead->userinfo->nick,command);
                    }
                }
            }

            if (!strcasecmp(command,"NOTICE")) 
            {
                sprintf(command,"%s",strtok(data," "));
                tuser = FindNick(head.users,command);

                if (tuser) 
                {
                    sprintf(temp,"%s",strtok(NULL,"\n"));
                    SendSock(tuser->socket,":%s!%s@%s NOTICE %s %s\n",
                            shead->userinfo->nick,shead->userinfo->ident,shead->userinfo->host,command,temp);
                    printf("Priv: [%s][%i]\n",data,tuser->socket);
                }
                else 
                {
                    SendSock(shead->socket,":%s 401 %s %s :No such nick/channel\n",
                            head.cf->servername,shead->userinfo->nick,command);
                }
            }

            if (!strcasecmp(command,"WHOIS")) 
            {
                tuser = FindNick(head.users,data);
                if (tuser) 
                {
                    SendSock(shead->socket,":%s 311 %s %s %s %s * :%s\n",
                            head.cf->servername,shead->userinfo->nick,tuser->nick,tuser->ident,tuser->host,tuser->name);
                    SendSock(shead->socket,":%s 312 %s %s %s :[serverdesc]\n",
                            head.cf->servername,shead->userinfo->nick,tuser->nick,tuser->server);
                    SendSock(shead->socket,":%s 317 %s %s %i %i :seconds idle, signon time\n",
                            head.cf->servername,shead->userinfo->nick,tuser->nick,tuser->idle,tuser->signon);
                    SendSock(shead->socket,":%s 318 %s %s :End of /WHOIS list.\n",
                            head.cf->servername,shead->userinfo->nick,tuser->nick);
                }
                else 
                {
                    SendSock(shead->socket,":%s 401 %s %s :No such nick/channel\n",
                            head.cf->servername,shead->userinfo->nick,data);
                }
            }

            if (!strcasecmp(command,"LIST")) 
            {
                DoListChannels(head.channels,shead->socket);        
            }

            if (!strcasecmp(command,"PART")) 
            {
                printf("Parting Fucken Channel [%s]\n",data);
                ListChannels(head.channels);
                tchan = FindChannel(head.channels,strtok(data," "));
                printf("Fucken GGGGGG\n");
                if (tchan) 
                {
                    printf("Chan Found\n");
                    if (FindChannelUser(tchan->chanusers,shead->userinfo->nick)) 
                    {
                        ShowChanPart(tchan,shead,head,strtok(NULL,"\n"));
                        DeleteChannelUser(&tchan->chanusers,shead->userinfo->nick);
                        DeleteUserChannel(&shead->userinfo->chans,tchan->name);
                    }
                }
                else 
                {
                    printf("Chan Not Found\n");
                    SendSock(shead->socket,"Not There Weeny\n");
                }
            }

            if (!strcasecmp(command,"JOIN")) 
            {
                tchan = FindChannel(head.channels,data);
                if (tchan) 
                {
                    printf("Channel Exists\n");
                    AddChannelUser(&tchan->chanusers,shead->userinfo->nick,"0");
                    AddUserChannel(&shead->userinfo->chans,tchan);
                    PrintChannels(shead->userinfo->chans);
                    PrintUsers(tchan->chanusers);
                }
                else 
                {
                    printf("New Channel\n");
                    tchan = AddChannel((struct slist *)&head,data);
                    AddChannelUser(&tchan->chanusers,shead->userinfo->nick,"@");
                    AddUserChannel(&shead->userinfo->chans,tchan);
                    PrintUsers(tchan->chanusers);
                    PrintChannels(shead->userinfo->chans);
                }

                SendSock(shead->socket,":%s!%s@%s JOIN :%s\n",shead->userinfo->nick,shead->userinfo->ident,shead->userinfo->host,data);
                SendSock(shead->socket,":%s 353 %s = %s :%s\n",head.cf->servername,shead->userinfo->nick,data,CNList(tchan->chanusers));
                SendSock(shead->socket,":%s 366 %s %s :End of /NAMES list.\n",head.cf->servername,shead->userinfo->nick,data);
                ShowChanJoin(tchan,shead,head);
            }

            if (!strcasecmp(command, "VERSION"))
            {
                SendSock(shead->socket, ":%s 351 %s :%s is running devel-ircd version %s\n",
                        head.cf->servername, shead->userinfo->nick, head.cf->servername, head.cf->version);
            }

            if (!strcasecmp(command, "LUSERS"))
            {
                SendSock(shead->socket, ":%s 251 %s :There are \002%d\002 users online.\n",
                        head.cf->servername, shead->userinfo->nick, numUsers);

            }


            else 
            {
                printf("Command: [%s]\n",command);
            }
            break;
        }
        default:
        {
            printf("Fucked\n");
            break;
        }
    }
    *lhead = head;
    return(0);
}


int SendMotd(struct slist head,Sock shead) 
{
    char data[1024];
    char mfread[512];
    FILE *fp;
    fp = fopen("ircd.motd", "r");
    if (!fp)
    {
        SendSock(shead->socket,":%s 422 %s :Server under repairs! MOTD File is missing\n",
                head.cf->servername,shead->userinfo->nick);
        return(0);
    }
    else
    {
        SendSock(shead->socket, ":%s 375 %s :- %s Message of the Day - \n", 
                head.cf->servername, shead->userinfo->nick, head.cf->servername);

        while (!feof(fp))
        {
            if (fgets(mfread, sizeof(mfread), fp))
            {
                if (mfread[0] == '#')
                    continue;

                SendSock(shead->socket, ":%s 372 %s :%s\n", 
                        head.cf->servername, shead->userinfo->nick, mfread);
            }
        }
        SendSock(shead->socket, ":%s 376 %s :-\n End of /MOTD command. \n-\n", 
                head.cf->servername, shead->userinfo->nick, head.cf->servername);

        SendSock(shead->socket, ":%s NOTICE %s :-\n", 
                head.cf->servername, shead->userinfo->nick);

        SendSock(shead->socket, ":%s NOTICE %s :- Please be warned this is a development ircd. It is not stable yet. :)\n",
                head.cf->servername, shead->userinfo->nick);

        SendSock(shead->socket, ":%s NOTICE %s :-\n", 
                head.cf->servername, shead->userinfo->nick);
 
    }
    fclose(fp);
    return 1;
}

int SendLogon(struct slist head,char *nick,int s) 
{
    char data[1024];
    SendSock(s,":%s 001 %s :Welcome to the %s IRC Network %s\n",head.cf->servername,nick,head.cf->network,nick);
    SendSock(s,":%s 002 %s :Your host is %s, running version %s\n",head.cf->servername,nick,head.cf->servername,head.cf->version);
    SendSock(s,":%s 003 %s :This server was put in service on [compile date] at [compile time]\n",head.cf->servername,nick); 
    SendSock(s,":%s 004 %s %s %s cdghkilmnosuw bciklmnopstv\n",head.cf->servername,nick,head.cf->servername,head.cf->version);
    return(0);
}
