/**********
 * Copyright (c) 2004 Greg Parker.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **********/

// fixme allow subsystems to register with Prefs for change notices 
// (rather than hardcoding those here)

#include "includes.h"
#include "formutils.h"
#include "zlib.h"
#include "data/prefs.h"
#include "ssh/ssh.h"
#include "rsrc/rsrc.h"

#include "connectionprefsform.h"


extern struct ssh_session_t *ss;

static void LoadConnectionPrefsForm(void) FORMS_SEGMENT;
static void SaveConnectionPrefsForm(void) FORMS_SEGMENT;

static void LoadConnectionPrefsForm(void)
{
    uint32_t value;
    char *str;

    // ciphers
    value = PrefsGetInt(prefCipherAES128CBC, 1);
    PrvSetControlValue(ConnectionPrefsFormAESCheckboxID, value ? 1 : 0);
    value = PrefsGetInt(prefCipher3DESCBC, 1);
    PrvSetControlValue(ConnectionPrefsForm3DESCheckboxID, value ? 1 : 0);

    // authmethods
    value = PrefsGetInt(prefAuthPublicKey, 1);
    PrvSetControlValue(ConnectionPrefsFormPublicKeyCheckboxID, value ? 1 : 0);
    value = PrefsGetInt(prefAuthPassword, 1);
    PrvSetControlValue(ConnectionPrefsFormPasswordCheckboxID, value ? 1 : 0);

    // compression
    // fixme zlib on default?
    if (ZLAvailable()) {
        value = PrefsGetInt(prefCompressZLib, 0);
        PrvSetControlValue(ConnectionPrefsFormZLibCheckboxID, value ? 1 : 0);
    } else {
        // indicate that zlib is not available
        PrvHideObjectByID(ConnectionPrefsFormZLibCheckboxID);
        PrvShowObjectByID(ConnectionPrefsFormZLibLabel1ID);
        PrvShowObjectByID(ConnectionPrefsFormZLibLabel2ID);
    }

    // terminal type
    str = PrefsGetString(prefTerminalType, "xterm");
    PrvSetFieldToValueByID(ConnectionPrefsFormTerminalFieldID, str);
    arena_free(str);
}


static void SaveConnectionPrefsForm(void)
{
    uint32_t value;
    int selection;

    // ciphers
    value = PrefsGetInt(prefCipherAES128CBC, 1);
    selection = PrvGetControlValue(ConnectionPrefsFormAESCheckboxID);
    if (value != selection) PrefsPutInt(prefCipherAES128CBC, selection);
    value = PrefsGetInt(prefCipher3DESCBC, 1);
    selection = PrvGetControlValue(ConnectionPrefsForm3DESCheckboxID);
    if (value != selection) PrefsPutInt(prefCipher3DESCBC, selection);

    // authmethods
    value = PrefsGetInt(prefAuthPublicKey, 1);
    selection = PrvGetControlValue(ConnectionPrefsFormPublicKeyCheckboxID);
    if (value != selection) PrefsPutInt(prefAuthPublicKey, selection);
    value = PrefsGetInt(prefAuthPassword, 1);
    selection = PrvGetControlValue(ConnectionPrefsFormPasswordCheckboxID);
    if (value != selection) PrefsPutInt(prefAuthPassword, selection);

    // compression
    if (ZLAvailable()) {
        value = PrefsGetInt(prefCompressZLib, 0);
        selection = PrvGetControlValue(ConnectionPrefsFormZLibCheckboxID);
        if (value != selection) PrefsPutInt(prefCompressZLib, selection);
    }

    // terminal type
    {
        char buf[21];
        PrvCopyFieldContents(ConnectionPrefsFormTerminalFieldID, buf);
        PrefsPutString(prefTerminalType, buf);
    }
}


Boolean ConnectionPrefsFormHandleEvent(EventPtr e)
{
    FormPtr frmP = FrmGetActiveForm();

    switch (e->eType) {
    case frmOpenEvent:
        LoadConnectionPrefsForm();
        FrmDrawForm(frmP);
        return true;

    case popSelectEvent: {
        if (e->data.popSelect.listID == ConnectionPrefsFormTerminalListID) {
            FieldPtr fld;
            char *str = LstGetSelectionText(e->data.popSelect.listP,
                                            e->data.popSelect.selection);
            PrvSetFieldToValueByID(ConnectionPrefsFormTerminalFieldID, str);
            fld = PrvGetObjectByID(ConnectionPrefsFormTerminalFieldID);
            FldEraseField(fld);
            FldDrawField(fld);
        }

        // DON'T let popup trigger see this event and change its name
        return true; 
    }

    case ctlSelectEvent:
        switch (e->data.ctlSelect.controlID) {
        case ConnectionPrefsFormOKButtonID:
            // save values; leave form
            SaveConnectionPrefsForm();
            FrmReturnToForm(0);
            return true;

        case ConnectionPrefsFormCancelButtonID:
            // DON'T save values; leave form
            FrmReturnToForm(0);
            return true;

        case ConnectionPrefsFormTerminalTriggerID: {
            // Before displaying terminal type popup, select the popup entry 
            // that matches the current field value, if any
            FieldPtr fld;
            ListPtr lst;
            char *fldStr;
            int i, count;

            fld = PrvGetObjectByID(ConnectionPrefsFormTerminalFieldID);
            fldStr = FldGetTextPtr(fld);
            lst = PrvGetObjectByID(ConnectionPrefsFormTerminalListID);
            count = LstGetNumberOfItems(lst);
            for (i = 0; i < count; i++) {
                char *lstStr = LstGetSelectionText(lst, i);
                if (0 == strcmp(lstStr, fldStr)) {
                    LstSetSelection(lst, i);
                    break;
                }
            }
            if (i == count) {
                LstSetSelection(lst, noListSelection);
            }
            
            return false; // continue with ordinary processing
        }

        // checkboxes

        // Require at least one cipher to be checked
        case ConnectionPrefsFormAESCheckboxID:
            if (!PrvGetControlValue(ConnectionPrefsFormAESCheckboxID)  &&  
                !PrvGetControlValue(ConnectionPrefsForm3DESCheckboxID))
            {
                PrvSetControlValue(ConnectionPrefsForm3DESCheckboxID, 1);
            }
            return false;
        case ConnectionPrefsForm3DESCheckboxID:
            if (!PrvGetControlValue(ConnectionPrefsFormAESCheckboxID)  &&  
                !PrvGetControlValue(ConnectionPrefsForm3DESCheckboxID))
            {
                PrvSetControlValue(ConnectionPrefsFormAESCheckboxID, 1);
            }
            return false;

        // Require at least one authmethod to be checked
        case ConnectionPrefsFormPublicKeyCheckboxID:
            if (!PrvGetControlValue(ConnectionPrefsFormPublicKeyCheckboxID)  &&
                !PrvGetControlValue(ConnectionPrefsFormPasswordCheckboxID))
            {
                PrvSetControlValue(ConnectionPrefsFormPasswordCheckboxID, 1);
            }
            return false;
        case ConnectionPrefsFormPasswordCheckboxID:
            if (!PrvGetControlValue(ConnectionPrefsFormPublicKeyCheckboxID)  &&
                !PrvGetControlValue(ConnectionPrefsFormPasswordCheckboxID))
            {
                PrvSetControlValue(ConnectionPrefsFormPublicKeyCheckboxID, 1);
            }
            return false;

        default:
            return false;
        }

    case frmCloseEvent:
        return false;

    default:
        return false;
    }
}
