#include <PalmOS.h>
#include <unix/sys_socket.h>
#include "network.h"
#include "helloRsc.h"



static void DebugError(const Char *msg, Err error)
{
    Char buffer[11];
    StrIToA(buffer, error);
    FrmCustomAlert(DebugAlert, "ERROR:\n", msg, buffer);
}


static void GetField(Char *buffer, UInt16 formid, UInt16 fieldid)
{
    FormType    *form;
    FieldType   *field;
    MemHandle   textH;
    Char        *textS;

    form = FrmGetFormPtr(formid);
    field=FrmGetObjectPtr(form, FrmGetObjectIndex(form, fieldid) );
    textH = FldGetTextHandle(field);
    if (textH) {
        textS = MemHandleLock(textH);
        StrCopy(buffer, textS);
        MemHandleUnlock(textH);
    } else {
        buffer[0] = '\0';
    }
}


static void DisplayField(const Char *buffer, UInt16 formid, UInt16 fieldid)
{
    FormType    *form;
    FieldType   *field;
    MemHandle   textH;
    Char        *text;
    Int16       buflen = StrLen(buffer)+1;

    form  = FrmGetFormPtr(formid);
    field = FrmGetObjectPtr(form, FrmGetObjectIndex(form, fieldid) );
    textH = FldGetTextHandle(field);

    if (textH) {
        Err     error = errNone;
        Int16   texlen;

        FldSetTextHandle(field, NULL);
        text   = MemHandleLock(textH);
        texlen = StrLen(text)+1;
        if (texlen<buflen) {
            MemHandleUnlock(textH);
            error = MemHandleResize(textH, buflen + sizeOf7BitChar(chrNull) );
            ErrFatalDisplayIf(error, "Out of memory");
            text   = MemHandleLock(textH);
        }
    } else {
        textH = MemHandleNew(buflen);
        ErrFatalDisplayIf(! textH, "Out of memory");
        text = MemHandleLock(textH);
    }

    StrCopy(text, buffer);
    MemHandleUnlock(textH);
    FldSetTextHandle(field, textH);
    FldDrawField(field);
}

static void Report(const Char* msg)
{
    DisplayField(msg, MainForm, MResultField);
}



    
static void CheckEmail ()
{
    AM_tcpip            amsocket;
    Err                 err;

    Char                hostname[41];
    Char                username[9];
    Char                password[33];
    Char                buffer[81];
    UInt16              bufmax = 80;
    Int16               bufdone= 0;
    

    GetField(hostname, MainForm, MServerField);
    if (StrLen(hostname)==0) {
        Report("E: please specify the network server");
        return;    
    }

    GetField(username, MainForm, MUserNameField);
    GetField(password, MainForm, MPasswordField);

    Report("CONNECT");

    /* setting up apropriate library access */
    err = AmNetLibLoad(&amsocket);
    if (err||amsocket.error) {
        Report("E: Cannot find or open Net library");
        return;    
    }

    err = AmNetLibConnect (&amsocket, hostname, 110, 5);
    if (err||amsocket.error) {
        Report("E: Cannot establish connection");
        AmNetLibUnload(&amsocket);
        return;    
    }

    do {
        bufdone = AmNetLibRecvLine(&amsocket, buffer, bufmax);
        if (amsocket.error || bufdone<1) {
            Report("E: no server greeting");
            break;
        }
        Report(buffer);

        StrCopy(buffer, "USER ");
        StrCat(buffer, username);
        Report(buffer);
        StrCat(buffer, "\n");
        bufdone = AmNetLibSendLine(&amsocket, buffer);
        if (amsocket.error || bufdone!=StrLen(buffer)) {
            Report("E: Cannot send USER");
            break;
        }

        bufdone = AmNetLibRecvLine(&amsocket, buffer, bufmax);
        if (amsocket.error || bufdone<1) {
            Report("E: no reply to USER");
            break;
        }
        Report(buffer);

        Report("PASS hash! (do not tell anybody)");
        StrCopy(buffer, "PASS ");
        StrCat(buffer, password);
        StrCat(buffer, "\n");
        bufdone = AmNetLibSendLine(&amsocket, buffer);
        if (amsocket.error || bufdone!=StrLen(buffer)) {
            Report("E: Cannot send PASS");
            break;
        }
    
        bufdone = AmNetLibRecvLine(&amsocket, buffer, bufmax);
        if (amsocket.error || bufdone<1) {
            Report("E: no reply to PASS");
            break;
        }
        Report(buffer);
    
        Report("STAT");
        StrCopy(buffer, "STAT\n");
        bufdone = AmNetLibSendLine(&amsocket, buffer);
        if (amsocket.error || bufdone!=StrLen(buffer)) {
            Report("E: Cannot send STAT");
            break;
        }
    
        bufdone = AmNetLibRecvLine(&amsocket, buffer, bufmax);
        if (amsocket.error || bufdone<1) {
            Report("E: no reply to STAT");
            break;
        }
        Report(buffer);

        StrCopy(buffer, "QUIT\n");
        bufdone = AmNetLibSendLine(&amsocket, buffer);
        if (amsocket.error || bufdone!=StrLen(buffer)) {
            Report("E: Cannot send QUIT");
            break;
        }
    
    } while (false); /* one pass do-while loop so that we can use break statement */    



    err = AmNetLibClose (&amsocket);
    if (err||amsocket.error) {
        Report("E: Cannot close connection");
        return;    
    }

    err = AmNetLibUnload(&amsocket);
    if (err||amsocket.error) {
        Report("E: Cannot close Net library");
        return;    
    }
}


    
static Err StartApplication(void)
{
    FrmGotoForm(MainForm);
    return errNone;
}


static void StopApplication(void)
{
}


static Boolean MainMenuHandleEvent(UInt16 menuID)
{
    Boolean    handled = false;
    FormType   *form;
    FieldType  *field;
    

    form = FrmGetActiveForm();
    field = FrmGetObjectPtr(form, FrmGetFocus(form));

    switch (menuID) {
        case MainEditUndo:
            FldUndo(field);
            handled = true;
            break;
        case MainEditCut:
            FldCut(field);
            handled = true;
            break;
        case MainEditCopy:
            FldCopy(field);
            handled = true;
            break;
        case MainEditPaste:
            FldPaste(field);
            handled = true;
            break;
        case MainEditSelectAll:
            FldSetSelection(field, 0, FldGetTextLength(field));
            handled = true;
            break;
            
        case MainEditKeyboard:
            SysKeyboardDialog(kbdDefault);
            handled = true;
            break;
            
        case MainEditGraffitiHelp:
            SysGraffitiReferenceDialog(referenceDefault);
            handled = true;
            break;
            
        case MainOptionsAbout:
            FrmAlert(AboutAlert);
            handled = true;
            break;
            
        default:
            break;
    }

    return handled;
}


static Boolean MainFormHandleEvent(EventPtr event)
{
    Boolean  handled = false;
    
    switch (event->eType) {
        case frmOpenEvent:
        {
            FormType  *form = FrmGetActiveForm();

            FrmDrawForm(form);
            FrmSetFocus(form, FrmGetObjectIndex(form, MServerField));
            handled = true;
        }
            break;

        case ctlSelectEvent:
            switch (event->data.ctlSelect.controlID) {
                case MCheckButton:
                    CheckEmail();
                    handled = true;
                    break;
                
                default:
                    break;
            }
            break;

        case menuEvent:
            handled = MainMenuHandleEvent(event->data.menu.itemID);
            break;

        default:
            break;
    }

    return handled;
}


static Boolean ApplicationHandleEvent(EventPtr event)
{
    FormType  *form;
    UInt16    formID;
    Boolean   handled = false;
    

    if (event->eType == frmLoadEvent) {
        formID = event->data.frmLoad.formID;
        form = FrmInitForm(formID);
        FrmSetActiveForm(form);
        
        switch (formID) {
            case MainForm:
                FrmSetEventHandler(form, MainFormHandleEvent);
                break;

            default:
                break;
        }
        handled = true;
    }

    return handled;
}


static void EventLoop(void)
{
    EventType  event;
    UInt16     error;

    
    do {
        EvtGetEvent(&event, evtWaitForever);
        if (! SysHandleEvent(&event))
            if (! MenuHandleEvent(0, &event, &error))
                if (! ApplicationHandleEvent(&event))
                    FrmDispatchEvent(&event);
    } while (event.eType != appStopEvent);
}


UInt32 PilotMain(UInt16 launchCode, MemPtr cmdPBP, UInt16 launchFlags)
{
    Err  err=errNone;


    switch (launchCode) {
        case sysAppLaunchCmdNormalLaunch:
            if ((err = StartApplication()) == 0) {
                EventLoop();
                StopApplication();
            }
            break;

        default:
            break;
    }

    return err;
}