#include <stdio.h>
#include <sp/spBaseLib.h>
#include <sp/spComponentLib.h>
#include <sp/spComponentMain.h>
#include <sp/spParamField.h>

static spComponent dialog = NULL;
static spComponent text_field = NULL;
static spComponent track_bar = NULL;

static void callbackFunc(spComponent component, void *data)
{
    spDebug(-10, "callbackFunc", "%s: reason = %d\n", spGetName(component), spGetCallbackReason(component));

    if (spIsSlider(component) == SP_TRUE) {
        int value;

        if (spGetSliderValue(component, &value) == SP_TRUE) {
            spDisplayMessage(component, NULL, "value = %d\n", value);
        }
    } else {
        char *string;

        if ((string = xspGetTextString(component)) != NULL) {
            spDisplayMessage(component, NULL, string);
            xspFree(string);
        }
    }
    
    return;
}

static void popdownDialogBoxCB(spComponent component, void *data)
{
    spCallbackReason reason;
    char *string;
    int value;

    reason = spGetCallbackReason(component);
    
    if (reason == SP_CR_CANCEL) {
        spDebug(1, "popdownDialogBoxCB", "SP_CR_CANCEL\n");
    } else if (reason == SP_CR_OK) {
        spDebug(1, "popdownDialogBoxCB", "SP_CR_OK\n");
    }
    
    if (reason == SP_CR_OK) {
        value = 0;
        spGetSliderValue(track_bar, &value);
        
        if ((string = xspGetTextString(text_field)) != NULL) {
            spDisplayMessage(component, "Message", "Text field = %s\nTrack bar = %d",
                             string, value);
            xspFree(string);
        }
    }
    
    spPopdownWindow(component);
    
    return;
}

static void dialogBoxCB(spComponent component, void *data)
{
    static char *list_strings[] =
    {
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4",
        "Item 5",
        NULL,
    };
    static char *file_filters[] =
    {
        "*.txt",
        "*.c",
        "*.h",
        "*",
        NULL,
    };
    
    spDebug(10, "dialogBoxCB", "in\n");

    if (spIsCreated(dialog) == SP_FALSE) {
        spDebug(10, "dialogBoxCB", "create new dialog box\n");
        dialog = spCreateDialogBox("Dialog Box",
                                   SppPopupStyle, SP_MODELESS_POPUP,
                                   SppCallbackFunc, popdownDialogBoxCB,
                                   SppCloseStyle, SP_UNMAP_CLOSE,
                                   NULL);
        
        /* create param field */
        text_field = spCreateParamField(dialog, "Text Field", 0,
                                        SppFieldOffset, 120,
                                        SppFieldSize, -80,
                                        SppEditable, SP_TRUE,
                                        SppFieldString, "Text",
                                        SppCallbackFunc, callbackFunc,
                                        NULL);
        spCreateParamField(dialog, "Combo Box", 0,
                           SppFieldType, SP_FIELD_TYPE_COMBO_BOX,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppFieldStrings, list_strings,
                           SppEditable, SP_TRUE,
                           SppCallbackFunc, callbackFunc,
                           NULL);
        spCreateParamField(dialog, "Directory Text", 0,
                           SppFieldType, SP_FIELD_TYPE_DIR_TEXT,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppEditable, SP_TRUE,
                           SppUseCheckBox, SP_TRUE,
                           SppCallbackFunc, callbackFunc,
                           NULL);
        spCreateParamField(dialog, "Open File Text", 0,
                           SppFieldType, SP_FIELD_TYPE_OPEN_FILE_TEXT,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppEditable, SP_TRUE,
                           SppUseCheckBox, SP_TRUE,
                           SppFileFilters, file_filters,
                           SppCallbackFunc, callbackFunc,
                           NULL);
        spCreateParamField(dialog, "Save File Text", 0,
                           SppFieldType, SP_FIELD_TYPE_SAVE_FILE_TEXT,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppEditable, SP_TRUE,
                           SppUseCheckBox, SP_TRUE,
                           SppFileFilters, file_filters,
                           SppCallbackFunc, callbackFunc,
                           NULL);
        spCreateParamField(dialog, "Color Text", 0,
                           SppFieldType, SP_FIELD_TYPE_COLOR_TEXT,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppEditable, SP_FALSE,
                           SppInitialColor, "white",
                           SppCallbackFunc, callbackFunc,
                           NULL);
        spCreateParamField(dialog, "Font Text", 0,
                           SppFieldType, SP_FIELD_TYPE_FONT_TEXT,
                           SppFieldOffset, 120,
                           SppFieldSize, -80,
                           SppEditable, SP_FALSE,
                           SppInitialFont, "-*-*-medium-r-normal--24-*-*-*-*-*-*-*",
                           SppCallbackFunc, callbackFunc,
                           NULL);
        track_bar = spCreateParamField(dialog, "Track Bar", 0,
                                       SppFieldType, SP_FIELD_TYPE_TRACK_BAR,
                                       SppFieldOffset, 120,
                                       SppFieldSize, -80,
                                       SppShowValue, SP_TRUE,
                                       SppTrackCallbackOn, SP_FALSE,
                                       SppCallbackFunc, callbackFunc,
                                       NULL);
    }
    
    spPopupWindow(dialog);
    
    spDebug(10, "dialogBoxCB", "popup done\n");

    return;
}

static spBool toplevelCB(spTopLevel toplevel, spTopLevelCallbackReason reason, void *data)
{
    spDebug(10, "toplevelCB", "reason = %d\n", reason);

    if (reason == SP_TL_CR_PERMISSION_RATIONALE_ASKED) {
        unsigned long asked_permissions = 0L;
        
        spGetTopLevelParams(toplevel,
                            SppAskedPermissions, &asked_permissions, 
                            NULL);

        spDebug(10, "toplevelCB", "asked_permissions = %lx\n", asked_permissions);
        
        if (asked_permissions) {
            if (spCreateMessageBox(NULL,
                                   NULL,
                                   "File dialog requires permission to access external directories.\nProceed?",
                                   SppDialogType, SP_QUESTION_DIALOG,
                                   SppMessageBoxButtonType, SP_MB_YES_NO,
                                   NULL) == SP_DR_NO) {
                return SP_FALSE;
            }
        }
    } else if (reason == SP_TL_CR_PERMISSION_CHANGED) {
        unsigned long accepted_permissions = 0L;
        unsigned long disabled_permissions = 0L;
        
        spGetTopLevelParams(toplevel,
                            SppAcceptedPermissions, &accepted_permissions, 
                            SppDisabledPermissions, &disabled_permissions, 
                            NULL);

        spDebug(10, "toplevelCB", "accepted_permissions = %lx, disabled_permissions = %lx\n",
                accepted_permissions, disabled_permissions);

        if (!(accepted_permissions & SP_PERMISSION_READ_EXTERNAL_STORAGE)
            || !(accepted_permissions & SP_PERMISSION_WRITE_EXTERNAL_STORAGE)) {
            spDisplayWarning(NULL, NULL, "Access to external directories is restricted.");
        }
    }
    
    return SP_TRUE;
}

int spMain(int argc, char *argv[])
{
    spTopLevel toplevel;
    spComponent frame;

    dialog = NULL;

    /* initialize toolkit */
    toplevel = spInitialize(&argc, &argv,
                            SppPermissions, SP_PERMISSION_READ_EXTERNAL_STORAGE | SP_PERMISSION_WRITE_EXTERNAL_STORAGE,
                            SppTopLevelCallbackFunc, toplevelCB,
                            NULL);
    
    /* create main window */
    frame = spCreateMainFrame("Param Dialog", NULL);

    /* create push button */
    spCreatePushButton(frame, "Create Dialog Box",
                       SppCallbackFunc, dialogBoxCB,
                       SppInitialWidth, 200,
                       NULL);
    spCreatePushButton(frame, "Quit",
                       SppCallbackFunc, spQuitCB,
                       SppInitialWidth, 200,
                       NULL);

    /* popup window */
    spPopupWindow(frame);
    
    /* main loop */
    return spMainLoop(toplevel);
}
