/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2005 by Kevin Ferrare
 *
 * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include "config.h"
#include "yesno.h"
#include "system.h"
#include "kernel.h"
#include "misc.h"
#include "lang.h"
#include "action.h"
#include "talk.h"
#include "settings.h"
#include "viewport.h"


struct gui_yesno
{
    const struct text_message * main_message;
    const struct text_message * result_message[2];
    
    struct viewport *vp;
    struct screen * display;
};

static void talk_text_message(const struct text_message * message, bool enqueue)
{
    int line;
    if(message)
    {
        for(line=0; line<message->nb_lines; line++)
        {
            long id = P2ID((unsigned char *)message->message_lines[line]);
            if(id>=0)
            {
                talk_id(id, enqueue);
                enqueue = true;
            }
        }
    }
}

static int put_message(struct screen *display,
                        const struct text_message * message,
                        int start, int max_y)
{
    int i;
    for(i=0; i<message->nb_lines && i+start<max_y; i++)
    {
        display->puts_scroll(0, i+start, 
                             P2STR((unsigned char *)message->message_lines[i]));
    }
    return i;
}
    
/*
 * Draws the yesno
 *  - yn : the yesno structure
 */
static void gui_yesno_draw(struct gui_yesno * yn)
{
    struct screen * display=yn->display;
    struct viewport *vp = yn->vp;
    int nb_lines, vp_lines, line_shift=0;

    display->set_viewport(vp);
    display->clear_viewport();
    nb_lines = yn->main_message->nb_lines;
    vp_lines = viewport_get_nb_lines(vp);

    if(nb_lines+3< vp_lines)
        line_shift=1;
    
    line_shift += put_message(display, yn->main_message,
                              line_shift, vp_lines);

    /* Space remaining for yes / no text ? */
    if(line_shift+2 <= vp_lines)
    {
        if(line_shift+3 <= vp_lines)
            line_shift++;
        display->puts(0, line_shift, str(LANG_CONFIRM_WITH_BUTTON));
#ifdef HAVE_LCD_BITMAP
        display->puts(0, line_shift+1, str(LANG_CANCEL_WITH_ANY));
#endif
    }
    display->update_viewport();
    display->set_viewport(NULL);
}

/*
 * Draws the yesno result
 *  - yn : the yesno structure
 *  - result : the result tha must be displayed :
 *    YESNO_NO if no
 *    YESNO_YES if yes
 */
static bool gui_yesno_draw_result(struct gui_yesno * yn, enum yesno_res result)
{
    const struct text_message * message=yn->result_message[result];
    struct viewport *vp = yn->vp;
    struct screen * display=yn->display;
    if(message==NULL)
        return false;
    display->set_viewport(vp);
    display->clear_viewport();
    put_message(yn->display, message, 0, viewport_get_nb_lines(vp));
    display->update_viewport();
    display->set_viewport(NULL);
    return(true);
}

enum yesno_res gui_syncyesno_run(const struct text_message * main_message,
                                 const struct text_message * yes_message,
                                 const struct text_message * no_message)
{
    int i;
    int button;
    int result=-1;
    bool result_displayed;
    struct gui_yesno yn[NB_SCREENS];
    struct viewport vp[NB_SCREENS];
    long talked_tick = 0;
    FOR_NB_SCREENS(i)
    {
        yn[i].main_message=main_message;
        yn[i].result_message[YESNO_YES]=yes_message;
        yn[i].result_message[YESNO_NO]=no_message;
        yn[i].display=&screens[i];
        yn[i].vp = &vp[i];
#ifdef HAVE_LCD_CHARCELLS 
        /* Quick fix. Viewports should really be enabled proper for charcell */
        viewport_set_defaults(yn[i].vp, i);
#else
        viewportmanager_theme_enable(i, true, yn[i].vp);
#endif
        screens[i].stop_scroll();
        gui_yesno_draw(&(yn[i]));
    }
    while (result==-1)
    {
        /* Repeat the question every 5secs (more or less) */
        if (global_settings.talk_menu
            && (talked_tick==0 || TIME_AFTER(current_tick, talked_tick+HZ*5)))
        {
            talked_tick = current_tick;
            talk_text_message(main_message, false);
        }
        button = get_action(CONTEXT_YESNOSCREEN, HZ*5);
        switch (button)
        {
            case ACTION_YESNO_ACCEPT:
                result=YESNO_YES;
                break;
            case ACTION_NONE:
            case SYS_CHARGER_DISCONNECTED:
                /* ignore some SYS events that can happen */
                continue;
            default:
                if(default_event_handler(button) == SYS_USB_CONNECTED)
                    return(YESNO_USB);
                result = YESNO_NO;
        }
    }

    FOR_NB_SCREENS(i)
        result_displayed=gui_yesno_draw_result(&(yn[i]), result);

    if (global_settings.talk_menu)
    {
        talk_text_message((result == YESNO_YES) ? yes_message 
                          : no_message, false);
        talk_force_enqueue_next();
    }
    if(result_displayed)
        sleep(HZ);

    FOR_NB_SCREENS(i)
    {
        screens[i].scroll_stop(yn[i].vp);
        viewportmanager_theme_undo(i, true);
    }
    return(result);
}
