/*
 * uimsgbox.c - Common SDL message box functions.
 *
 * Written by
 *  Marco van den Heuvel <blackystardust68@yahoo.com>
 *  Greg King <greg.king5@verizon.net>
 *
 * This file is part of VICE, the Versatile Commodore Emulator.
 * See README for copyright notice.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA.
 *
 */

#include "vice_sdl.h"
#include "types.h"

#include <assert.h>
#include <string.h>

#include "lib.h"
#include "resources.h"
#include "sound.h"
#include "ui.h"
#include "uimenu.h"
#include "uimsgbox.h"
#include "vsync.h"

#define MAX_MSGBOX_LEN 28


/** \brief  Table of number of buttons for each `message mode` enum value
 */
static int msg_mode_buttons[] = {
    1,  /* MESSAGE_OK */
    2,  /* MESSAGE_YESNO */
    3,  /* MESSAGE_CPUJAM */
    5,  /* MESSAGE_UNIT_SELECT */
};



static menu_draw_t *menu_draw;

/** \brief  Show a message box with some buttons
 *
 * \param[in]   title           Message box title
 * \param[in]   message         Message box message/prompt
 * \param[in]   message_mode    Type of message box to display (defined in .h)
 *
 * \return  index of selected button, or -1 on cancel (Esc)
 */
static int handle_message_box(const char *title, const char *message, int message_mode)
{
    char *text, *pos;
    unsigned int msglen, len;
    int before;
    int x;
    char template[] = "\335                            \335";
    unsigned int j = 5;
    int active = 1;
    int cur_pos = 0;
    int button_count;

    /* determine button count for requested `message mode` */
    if (message_mode < 0 || message_mode >= (int)(sizeof msg_mode_buttons / sizeof msg_mode_buttons[0])) {
        fprintf(stderr, "%s:%d:%s: illegal `message_mode` value %d\n",
               __FILE__, __LINE__, __func__, message_mode);
        return -1;
    }
    button_count = msg_mode_buttons[message_mode];

    /* print the top edge of the dialog. */
    sdl_ui_clear();
    sdl_ui_print_center("\260\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\256", 2);

    /* make sure that the title length is not more than 28 chars. */
    len = strlen(title);
    assert(len <= MAX_MSGBOX_LEN);

    /* calculate the position in the template to copy the title to. */
    before = (MAX_MSGBOX_LEN - len) / 2;

    /* copy the title into the template. */
    memcpy(template + 1 + before, title, len);

    /* print the title part of the dialog. */
    sdl_ui_print_center(template, 3);

    /* print the title/text separator part of the dialog. */
    sdl_ui_print_center("\253\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\263", 4);

    text = lib_stralloc(message);
    msglen = (unsigned int)strlen(text);

    /* substitute forward slashes and spaces for backslashes and newline
     * characters.
     */
    pos = text + msglen;
    do {
        switch (*--pos) {
            case '\\':
                *pos = '/';
                break;
            case '\n':
                *pos = ' ';
            default:
                break;
        }
    } while (pos != text);

    while (msglen != 0) {
        len = msglen;
        if (len > MAX_MSGBOX_LEN) {
            /* fold lines at the space that is closest to the right edge. */
            len = MAX_MSGBOX_LEN + 1;
            while (pos[--len] != ' ') {
                /* if a word is too long, fold it anyway! */
                if (len == 0) {
                    len = MAX_MSGBOX_LEN;
                    break;
                }
            }
        }

        /* erase the old line. */
        memset(template + 1, ' ', MAX_MSGBOX_LEN);

        /* calculate the position in the template to copy the message line to. */
        before = (MAX_MSGBOX_LEN - len) / 2;

        /* copy the message line into the template. */
        memcpy(template + 1 + before, pos, len);

        /* print the message line. */
        sdl_ui_print_center(template, j);

        /* advance to the next message line. */
        j++;
        msglen -= len;
        pos += len;

        /* if the text was folded at a space, then move beyond that space. */
        if (*pos == ' ') {
            msglen--;
            pos++;
        }
    }
    lib_free(text);

    /* print any needed buttons. */
    sdl_ui_print_center("\335                            \335", j);
    switch (message_mode) {
        case MESSAGE_OK:
            sdl_ui_print_center("\335            \260\300\300\256            \335", j + 1);
            x = sdl_ui_print_center("\335            \335OK\335            \335", j + 2);
            sdl_ui_print_center("\335            \255\300\300\275            \335", j + 3);
            break;
        case MESSAGE_YESNO:
            sdl_ui_print_center("\335      \260\300\300\300\256       \260\300\300\256      \335", j + 1);
            x = sdl_ui_print_center("\335      \335YES\335       \335NO\335      \335", j + 2);
            sdl_ui_print_center("\335      \255\300\300\300\275       \255\300\300\275      \335", j + 3);
            break;
        case MESSAGE_UNIT_SELECT:
            /* Present a selection of '8', '9', '10', '11' or 'SKIP' */
            sdl_ui_print_center("\335  \260\300\256 \260\300\256 \260\300\300\256 \260\300\300\256 \260\300\300\300\300\256  \335", j + 1);
            x = sdl_ui_print_center("\335  \3358\335 \3359\335 \33510\335 \33511\335 \335SKIP\335  \335", j + 2);
            sdl_ui_print_center("\335  \255\300\275 \255\300\275 \255\300\300\275 \255\300\300\275 \255\300\300\300\300\375  \335", j + 3);

            break;
        case MESSAGE_CPUJAM:
        default:
            sdl_ui_print_center("\335 \260\300\300\300\300\300\256  \260\300\300\300\300\300\300\300\256  \260\300\300\300\300\256 \335", j + 1);
            x = sdl_ui_print_center("\335 \335RESET\335  \335MONITOR\335  \335CONT\335 \335", j + 2);
            sdl_ui_print_center("\335 \255\300\300\300\300\300\275  \255\300\300\300\300\300\300\300\275  \255\300\300\300\300\275 \335", j + 3);
            break;
    }

    /* print the bottom part of the dialog. */
    sdl_ui_print_center("\255\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\300\275", j + 4);

    x += (menu_draw->max_text_x - 30) / 2;
    while (active) {
        switch (message_mode) {
            case MESSAGE_OK:
                sdl_ui_reverse_colors();
                sdl_ui_print_center("OK", j + 2);
                sdl_ui_reverse_colors();
                break;
            case MESSAGE_YESNO:
                if (cur_pos == 0) {
                    sdl_ui_reverse_colors();
                }
                sdl_ui_print("YES", x - 22, j + 2);
                sdl_ui_reverse_colors();
                sdl_ui_print("NO", x - 10, j + 2);
                if (cur_pos == 1) {
                    sdl_ui_reverse_colors();
                }
                break;

            case MESSAGE_UNIT_SELECT:
                sdl_ui_print_center("\335  \3358\335 \3359\335 \33510\335 \33511\335 \335SKIP\335  \335", j + 2);
 
                sdl_ui_reverse_colors();
                switch (cur_pos) {
                    case 0:
                        sdl_ui_print("8", x - 26, j + 2);
                        break;
                    case 1:
                        sdl_ui_print("9", x - 22, j + 2);
                        break;
                    case 2:
                        sdl_ui_print("10", x - 18, j + 2);
                        break;
                    case 3:
                        sdl_ui_print("11", x - 13, j + 2);
                        break;
                    case 4:
                        sdl_ui_print("SKIP", x - 8, j + 2);
                        break;
                    default:
                        break;
                }
                sdl_ui_reverse_colors();
                break;
            case MESSAGE_CPUJAM:
            default:
                if (cur_pos == 0) {
                    sdl_ui_reverse_colors();
                }
                sdl_ui_print("RESET", x - 27, j + 2);
                if (cur_pos < 2) {
                    sdl_ui_reverse_colors();
                }
                sdl_ui_print("MONITOR", x - 18, j + 2);
                if (cur_pos > 0) {
                    sdl_ui_reverse_colors();
                }
                sdl_ui_print("CONT", x - 7, j + 2);
                if (cur_pos == 2) {
                    sdl_ui_reverse_colors();
                }
                break;
        }

        sdl_ui_refresh();

        switch (sdl_ui_menu_poll_input()) {
            case MENU_ACTION_CANCEL:
            case MENU_ACTION_EXIT:
                cur_pos = -1;
                active = 0;
                break;
            case MENU_ACTION_SELECT:
                active = 0;
                break;
            case MENU_ACTION_LEFT:
            case MENU_ACTION_UP:
                if (message_mode != MESSAGE_OK) {
                    cur_pos--;
                    if (cur_pos < 0) {
                        cur_pos = button_count - 1;
                    }
                }
                break;
            case MENU_ACTION_RIGHT:
            case MENU_ACTION_DOWN:
                if (message_mode != MESSAGE_OK) {
                    cur_pos++;
                    if (cur_pos >= button_count) {
                        cur_pos = 0;
                    }
                }
                break;
            default:
                SDL_Delay(10);
                break;
        }
    }
    return cur_pos;
}

static int activate_dialog(const char *title, const char *message, int message_mode)
{
    int retval;

    sdl_ui_activate_pre_action();
    retval = handle_message_box(title, message, message_mode);
    sdl_ui_activate_post_action();

    return retval;
}

int message_box(const char *title, char *message, int message_mode)
{
    sdl_ui_init_draw_params();

    menu_draw = sdl_ui_get_menu_param();

    if (!sdl_menu_state) {
        return activate_dialog(title, (const char *)message, message_mode);
    }
    return handle_message_box(title, (const char *)message, message_mode);
}
