#include "SUMA_suma.h"

/*
 update 03/08/2017 Justin Rajendra
 changed to be 3 buttons with different text for each button
 returns 1,2,3 for the 3 buttons
 if you don't provide any button labels, it will show Ok
 Based on SUMA_prompt_user.c 
 */


static char * read_file_text(FILE * fp);  /* 29 Jun 2012 [rickr] */

// help!
void usage_prompt_popup (SUMA_GENERIC_ARGV_PARSE *ps)
{
    static char FuncName[]={"usage_prompt_popup"};
    int i;
    printf (
            "\n"
            "Usage: prompt_popup -message MESSAGE -button HELLO \n"
            "  -message MESSAGE: Pops a window prompting the user with MESSAGE.\n"
            "                    Program does not return until user responds.\n"
            "                    note: if MESSAGE is '-', it is read from stdin\n"
            "  -pause MESSAGE:   Same as -message to match the old prompt_user\n"
            "  -button LABEL:    What do you want the buttons to say?\n"
            "                    You can give up to three -button for three buttons.\n"
            "                    Returns integer 1, 2, or 3.\n"
            "                    If there is no -button, there will be one button 'Ok'\n"
            "  -b LABEL:         Same as -button.\n"
            "  -timeout TT:      Timeout in seconds of prompt message. Default answer\n"
            "                    is returned if TT seconds elapse without user\n"
            "                    input.\n"
            "  -to TT:           Same as -timeout TT\n"
            "\n"
            "example: prompt_popup -message 'Best disco ever?' -b Earth -b Wind -b Fire\n"
            "\n");

    printf("Justin Rajendra March 2017 (stolen mostly from Ziad S. Saad)\n");
    exit(0);
}

// stolen from SUMA_PauseForUser
int SUMA_PauseForUserDisco(  Widget parent,char *question,char *yes_user,char *no_user,
                           char *help_user,SUMA_WINDOW_POSITION pos,XtAppContext *app,
                           int withCancel,int withHelp,float timeout)
{
    static char FuncName[]={"SUMA_PauseForUserDisco"};
    static Widget dialog = NULL; /* static to avoid multiple creation */

    // for each button (defaults are Ok, Cancel, Help)
    Widget YesWid;
    Widget NoWid;
    Widget HelpWid;

    int ii;
    XmString text, yes, no, help;
    struct  timeval  tt;
    static int answer;
    SUMA_Boolean LocalHead = NOPE;

    SUMA_ENTRY;
    if (!parent) {
        /* look for the first non-null sv->X->TOPLEVEL */
        ii = 0;
        while (ii<SUMAg_N_SVv && !(parent=SUMAg_SVv[ii].X->TOPLEVEL)) {
            ++ii;
        }
    }
    if (!parent) { /* no widgets, go command line */
        SUMA_PAUSE_PROMPT_STDIN(question);
        SUMA_RETURN(SUMA_YES);
    }
    if (!dialog) {
        SUMA_LH("Creating Dialog");
        dialog = XmCreateQuestionDialog (parent, "dialog", NULL, 0);

        // check to see if you want the 2nd and 3rd button
        if (!withHelp) {
            XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_HELP_BUTTON));
        } else {
            XtAddCallback (dialog, XmNhelpCallback, SUMA_response, &answer);
        }
        if (!withCancel) {
            XtUnmanageChild (XmMessageBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON));
        } else {
            XtAddCallback (dialog, XmNcancelCallback, SUMA_response, &answer);
        }

        // always want the ok button
        XtAddCallback (dialog, XmNokCallback, SUMA_response, &answer);

    } else {
        SUMA_LH("Reusing Dialog (SLOW SLOW SLOW)");
    }

    // set time
    SUMA_etime(&tt, 0);

    // text for buttons
    text = XmStringCreateLocalized (question);
    yes = XmStringCreateLocalized (yes_user);
    no = XmStringCreateLocalized (no_user);
    help = XmStringCreateLocalized (help_user);
    answer = 0;

    // set to widget?
    XtVaSetValues (dialog,
                   XmNmessageString,      text,
                   XmNokLabelString,      yes,
                   XmNcancelLabelString,  no,
                   XmNhelpLabelString,    help,
                   XmNdefaultButtonType,  XmDIALOG_OK_BUTTON,
                   NULL);
    // free!
    XmStringFree (text);
    XmStringFree (yes);
    XmStringFree (no);
    XmStringFree (help);

    // set the values of the standard buttons
    YesWid = XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON);
    NoWid = XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON);
    HelpWid = XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON);

    // return values for each button (change here if you want different integers)
    XtVaSetValues(YesWid, XmNuserData, 1, NULL);
    XtVaSetValues(NoWid, XmNuserData, 2, NULL);
    XtVaSetValues(HelpWid, XmNuserData, 3, NULL);

    XtManageChild (dialog);
    XtPopup (XtParent (dialog), XtGrabNone);

    if (pos != SWP_DONT_CARE) SUMA_PositionWindowRelative(dialog, parent, pos);
    if (!app) app = &(SUMAg_CF->X->App);

    if (timeout < 0.0) { /* no timer */
        while ( (answer == 0 && XtIsManaged(dialog)) ) {
            XtAppProcessEvent (*app, XtIMAll);
        }
    } else {
        while ( (answer == 0 && XtIsManaged(dialog)) ) {
            if (timeout < 0.0 || SUMA_etime(&tt,1) < timeout) {
                if (XtAppPending(*app)) { XtAppProcessEvent (*app, XtIMAll); }
            } else {
                XtVaGetValues(YesWid, XmNuserData, &answer, NULL);
                break;
            }
        }
    }  // end time out
#if 1
    SUMA_LH("destroying dialog");

    XtDestroyWidget(dialog);   /* This won't get the widget off of the screen
                                unless there is an XtAppMainLoop running.
                                When that is not the case, you need to
                                trigger an event processing call, see
                                SUMA_prompt_user.c for an example */

    dialog = NULL;
#else /* bad, takes for ever to come back up.
Same for repeated calls of ForceUser if created for the first
time from DriveSuma and not from the interface with, say 'shft+Esc'
See bit of illustration code in SUMA_Engine where PauseForUser
is called*/
    XtUnmanageChild(dialog);
#endif
    SUMA_RETURN(answer);
}

// parse the arguments
SUMA_GENERIC_PROG_OPTIONS_STRUCT *SUMA_prompt_popup_ParseInput(char *argv[],int argc,
                                                              SUMA_GENERIC_ARGV_PARSE *ps)
{
    static char FuncName[]={"SUMA_prompt_popup_ParseInput"};
    SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt=NULL;
    int kar;
    SUMA_Boolean brk;
    SUMA_Boolean LocalHead = NOPE;

    SUMA_ENTRY;
    Opt = SUMA_Alloc_Generic_Prog_Options_Struct();
    Opt->ps = ps;  /* just hold it there for convenience */
    Opt->flt1 = -1.0;

    // for number of answers
    Opt->n_in_namev = 0;

    kar = 1;
    brk = NOPE;
    while (kar < argc) { /* loop across command line options */
        if (strcmp(argv[kar], "-h") == 0 || strcmp(argv[kar], "-help") == 0) {
            ps->hverb = 1;
            usage_prompt_popup(ps);
            exit (0);
        }

        SUMA_SKIP_COMMON_OPTIONS(brk, kar);

        if (!brk && (strcmp(argv[kar], "-debug") == 0))
        {
            if (kar+1 >= argc)
            {
                fprintf (SUMA_STDERR, "need a number after -debug \n");
                exit (1);
            }
            Opt->debug = atoi(argv[++kar]);
            brk = YUP;
        }

        // the question
        if (!brk && (
                     (strcmp(argv[kar], "-message") == 0) ||
                     (strcmp(argv[kar], "-pause") == 0)) )
        {
            if (kar+1 >= argc)
            {
                fprintf (SUMA_STDERR, "need a string after -message \n");
                exit (1);
            }
            Opt->b1 = 1;
            Opt->in_name = argv[++kar];
            brk = YUP;
            if (!strcmp(Opt->in_name, "-")) Opt->in_name = read_file_text(stdin);
        }

        // timing
        if (!brk && (
                     (strcmp(argv[kar], "-timeout") == 0) ||
                     (strcmp(argv[kar], "-to") == 0)) )
        {
            if (kar+1 >= argc)
            {
                fprintf (SUMA_STDERR,
                         "need a time in seconds after -timeout/-to \n");
                exit (1);
            }
            Opt->flt1 = atof(argv[++kar]);
            brk = YUP;
        }

        // answers (check for how many there are)
        if (!brk && (
                     (strcmp(argv[kar], "-button") == 0) ||
                     (strcmp(argv[kar], "-b") == 0)) )
        {
            if (kar+1 >= argc)
            {
                fprintf (SUMA_STDERR,"Need a button label!\n");
                exit (1);
            }
            if ( Opt->n_in_namev >= 3 )
            {
                fprintf (SUMA_STDERR,"You only get 3 buttons!\n");
                exit (1);
            }
            // increment for each answer and save to that index
            Opt->n_in_namev++;
            Opt->in_namev[Opt->n_in_namev] = argv[++kar];
            brk = YUP;
        }

        // oops
        if (!brk && !ps->arg_checked[kar]) {
            SUMA_S_Errv("Option %s not understood.\n"
                        "Try -help for usage\n",
                        argv[kar]);
            exit (1);
        } else {
            brk = NOPE;
            kar ++;
        }
    }
    SUMA_RETURN(Opt);
}

/* return all of fp (stdin, probably) in a string */
static char * read_file_text(FILE * fp)
{
    static char FuncName[]={"read_file_text"};
    char * str, ch;
    int    i, len, nalloc;

    SUMA_ENTRY;

    if ( ! fp ) SUMA_RETURN(NULL);

    str = NULL;
    len = 0;
    nalloc = 1;  /* add space for nul term */
    while ( ! feof(fp) ) {
        nalloc += 100; /* read block size */
        str = realloc(str, nalloc * sizeof(char));
        if( !str ) {
            fprintf(stderr,"** RFT alloc fail on len %d\n", nalloc);
            SUMA_RETURN(NULL);
        }
        for( i=0; i < 100 && !feof(fp); i++ )
            str[len++] = fgetc(fp);
        if( feof(fp) ) len--;
    }
    str[len] = '\0'; /* terminate */

    SUMA_RETURN(str);
}

int main (int argc,char *argv[])
{/* Main */
    static char FuncName[]={"prompt_popup"};
    SUMA_GENERIC_PROG_OPTIONS_STRUCT *Opt;
    SUMA_GENERIC_ARGV_PARSE *ps=NULL;
    char * esc_str = NULL;
    int ii;
    int cancel_sel;
    int help_sel;
    Widget w=NULL;
    XtAppContext    app;
    XEvent ev;
    XtInputMask pp;
    SUMA_Boolean LocalHead = NOPE;
    SUMA_STANDALONE_INIT;
    SUMA_mainENTRY;

    /* Allocate space for DO structure */
    SUMAg_DOv = SUMA_Alloc_DisplayObject_Struct (SUMA_MAX_DISPLAYABLE_OBJECTS);
    ps = SUMA_Parse_IO_Args(argc, argv, "");

    if (argc < 2) {
        usage_prompt_popup(ps);
        exit (1);
    }

    // parse the arguments
    Opt = SUMA_prompt_popup_ParseInput (argv, argc, ps);

    // see how many answers and give 1-3 buttons
    if ( Opt->n_in_namev == 1 ) {
        cancel_sel = 0;
        help_sel = 0;
    } else if ( Opt->n_in_namev == 2 ) {
        cancel_sel = 1;
        help_sel = 0;
    } else if (Opt->n_in_namev == 0){
        cancel_sel = 0;
        help_sel = 0;
    }  else  {
        cancel_sel = 1;
        help_sel = 1;
    }

    w = XtOpenApplication(&app, "prompt_popup",
                          NULL, 0, &argc, argv,
                          SUMA_get_fallbackResources(),
                          topLevelShellWidgetClass, NULL, 0);

    switch (Opt->b1) {
        case 1:
            /* apply some escape characters     31 Jul 2009 [rickr] */
            esc_str = unescape_unix_str(Opt->in_name);

            // popup buttons and return int answer
            ii = SUMA_PauseForUserDisco(w, esc_str,
                                        Opt->in_namev[1],
                                        Opt->in_namev[2],
                                        Opt->in_namev[3],
                                        SWP_POINTER_LEFT_BOTTOM,&app,
                                        cancel_sel,help_sel,Opt->flt1);
            fprintf(SUMA_STDOUT,"%d\n", ii);
            break;
        default:
            SUMA_S_Err("Bad opt");
            exit(1);

    }

    /* because you have no XtAppMainLoop, you'll need to process the next
     event for when the XtDestroy command on w's child takes effect. So you'll
     just have this zombie widget that stares at you.
     In this simple command line program, the widget dies anyway when you
     exit the program, so the call below is a teaching moment for when
     functions like SUMA_PauseForUser are called from programs without an
     XtAppMainLoop.
     See also SUMA_PAUSE_PROMPT macro */

    while ((pp = XtAppPending(app))) {
        XtAppProcessEvent(app, pp);
    }
    if (Opt->debug > 2) LocalHead = YUP;
    if (ps) SUMA_FreeGenericArgParse(ps); ps = NULL;
    if (Opt) Opt = SUMA_Free_Generic_Prog_Options_Struct(Opt);
    if (!SUMA_Free_CommonFields(SUMAg_CF))
        SUMA_error_message(FuncName,"SUMAg_CF Cleanup Failed!",1);

    if( esc_str ) free(esc_str);

    exit(0);

}
