/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#if 0
#define debugbut
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "os.h"
#include "wimp.h"
#include "wimpt.h"
#include "event.h"
#include "dbox.h"
#include "msgs.h"

#include "malloc+.h"
#include "listfiles.h"
#include "memmanage.h"
#include "allerrs.h"
#include "actionwind.h"
#include "Buttons.h"
#include "debug.h"

#define No 0
#define Yes (!No)


static void null_activity( action_environment * );
static void pause_operation( action_environment * );
static void continue_operation( action_environment * );
static void skip_file( action_environment * );
static void operate_on_file( action_environment * );
static void to_end_of_list( action_environment * );
static void skip_operation( action_environment * );
static void retry_operation( action_environment * );
static void restart_operation( action_environment * );
static void run_object( action_environment * );
static void view_object( action_environment * );

const button_set abort_pause_buttons =
{
        {
                No,
                abort_operation,
                null_activity,
                null_activity,
                pause_operation,
                null_activity,
                {
                        "3",
                        "",
                        "",
                        "4",
                        ""
                }
        },
        {
                "5",
                NULL,
                NULL,
                "6",
                NULL
        }
};

const button_set confirm_buttons =
{
        {
                Yes,
                abort_operation,
                skip_file,
                operate_on_file,
                to_end_of_list,
                null_activity,
                {
                        "3",
                        "8",
                        "9",
                        "10",
                        ""
                }
        },
        {
                "5",
                "11",
                "12",
                "13",
                NULL
        }
};

const button_set ok_button =
{
        {
                Yes,
                null_activity,
                null_activity,
                null_activity,
                null_activity,
                abort_operation,
                {
                        "",
                        "",
                        "",
                        "",
                        "14"
                }
        },
        {
                NULL,
                NULL,
                NULL,
                NULL,
                "15"
        }
};

const button_set norestart_button =
{
        {
                Yes,
                abort_operation,
                null_activity,
                null_activity,
                retry_operation,
                skip_operation,
                {
                        "3",
                        "",
                        "",
                        "16",
                        "8"
                }
        },
        {
                "5",
                NULL,
                NULL,
                "17",
                "18"
        }
};

const button_set restart_button =
{
        {
                Yes,
                abort_operation,
                skip_operation,
                restart_operation,
                retry_operation,
                null_activity,
                {
                        "5",
                        "8",
                        "19",
                        "16",
                        ""
                }
        },
        {
                "5",
                "18",
                "20",
                "17",
                NULL
        }
};

const button_set abort_retry_buttons =
{
        {
                Yes,
                abort_operation,
                null_activity,
                null_activity,
                retry_operation,
                null_activity,
                {
                        "3",
                        "",
                        "",
                        "16",
                        ""
                }
        },
        {
                "5",
                NULL,
                NULL,
                "17",
                NULL
        }
};

const button_set run_view_buttons =
{
        {
                Yes,
                abort_operation,
                run_object,
                view_object,
                continue_operation,
                null_activity,
                {
                        "3",
                        "21",
                        "22",
                        "23",
                        ""
                }
        },
        {
                "5",
                "24",
                "25",
                "26",
                NULL
        }
};

const button_set open_buttons =
{
        {
                Yes,
                abort_operation,
                null_activity,
                null_activity,
                continue_operation,
                run_object,
                {
                        "3",
                        "",
                        "",
                        "23",
                        "27"
                }
        },
        {
                "5",
                NULL,
                NULL,
                "26",
                "28"
        }
};

static void set_button( action_environment *env, int button, const char *text )
{
        int dbox_handle = dbox_syshandle( env->status_box );


        if ( text != NULL )
        {
                /*
                        Ensure button exists before setting field
                */
                wimp_set_icon_state( dbox_handle, button, 0, wimp_IDELETED | wimp_IREDRAW );
                dbox_setfield( env->status_box, button, msgs_lookup((char *)text) );
        }
        else
        {
                wimp_redrawstr r;
                wimp_icon icondata;
                os_error *err;

                /*
                     delete button
                */
                err = wimp_get_icon_info( dbox_handle, button, &icondata );

                if ( !err )
                {
                        wimp_set_icon_state( dbox_handle, button, wimp_IDELETED | wimp_IREDRAW, wimp_IDELETED | wimp_IREDRAW );

                        r.w = dbox_handle;
                        r.box = icondata.box;

                        wimp_force_redraw( &r );
                }
        }
}

static void set_all_buttons( action_environment *env, const button_texts *texts )
{
        set_button( env, Abort_Button, texts->abort_text );
        set_button( env, No_Skip_Button, texts->no_skip_text );
        set_button( env, Yes_Retry_Button, texts->yes_retry_text );
        set_button( env, Misc_Button, texts->misc_text );
        set_button( env, Skip_Button, texts->skip_text );
}

void switch_buttons( action_environment *env, const button_set *new_buttons )
{
        env->button_actions = new_buttons->actions;
        set_all_buttons( env, &new_buttons->texts );

        if ( new_buttons->actions.requires_interaction )
        {
                /*
                     Pop up the dialogue box and turn off NULL events
                */
                dbox_showstatic( env->status_box );

                show_faster_stuff( env );

                event_setmask( wimp_EMNULL | wimp_EMPTRLEAVE | wimp_EMPTRENTER | wimp_EMUSERDRAG );
        }
        else
        {
                if ( !env->verbose )
                {
                        switch_dbox_on_off( env, -1, Remove_Delay );
                }

                /*
                        Things might have changed, so update ourselves
                */
                read_next_node_parameters( env->test_search );

                event_setmask( wimp_EMPTRLEAVE | wimp_EMPTRENTER | wimp_EMUSERDRAG );
        }
}

void abort_operation( action_environment *env )
{
        dispose_search_context( env->test_search );

        exit( 0 );
}

static void pause_operation( action_environment *env )
{
        char info_buffer[ Info_Field_Length + 10 ];

        set_button( env, Misc_Button, "26" );

        env->button_actions.button_helps[ Misc_Button - Abort_Button ] = "79";

        env->button_actions.misc_action = continue_operation;

        strcpy(info_buffer, "80a");
        strcat(info_buffer, env->current_info_token);
        sprintf(info_buffer, msgs_lookup(info_buffer), tolower(env->current_info[0]), &env->current_info[1]);

        dbox_setfield( env->status_box, Top_Info_Field, info_buffer );

        last_top_info_field = info_buffer;

        dbox_showstatic( env->status_box );

        event_setmask( wimp_EMNULL | wimp_EMPTRLEAVE | wimp_EMPTRENTER | wimp_EMUSERDRAG );
}

static void continue_operation( action_environment *env )
{
        switch_buttons( env, &abort_pause_buttons );
}

static void null_activity( action_environment *env )
{
        env = env;     /* keep the compiler quiet */
}

/*
     confirm Yes button
*/
static void operate_on_file( action_environment *env )
{
        switch_buttons( env, &abort_pause_buttons );
}

/*
     confirm Quiet button
*/
static void to_end_of_list( action_environment *env )
{
        switch_buttons( env, &abort_pause_buttons );

        env->confirm = No;
}

/*
     confirm Skip button
*/
static void skip_file( action_environment *env )
{
        env->action = Next_File;

        skip_list_file( env->test_search );

        switch_buttons( env, &abort_pause_buttons );
}

/*
     error Skip button
*/
static void skip_operation( action_environment *env )
{
        if ( env->action == Next_File )
        {
                skip_failed_selection( env->test_search );
        }
        else
        {
                switch ( env->operation )
                {
                case Action_Copying:
                case Action_CopyMoving:
                case Action_CopyLocal:
                        if ( env->action == Check_Full_Reading )
                        {
                                skip_file_read();
                                switch_to_reading( env );
                        }
                        else if ( env->action == Check_Empty_Writing )
                        {
                                skip_file_write();
                                switch_to_writing( env );
                        }
                        else
                        {
                                env->action = Next_File;
                        }
                     break;

                case Action_Moving:
                case Action_Deleting:
                case Action_Setting_Access:
                case Action_Setting_Type:
                case Action_Counting:
                case Action_Stamping:
                case Action_Finding:
                        env->action = Next_File;
                        break;
                }
        }

        switch_buttons( env, &abort_pause_buttons );
}

static void run_object( action_environment *env )
{
        char *filename;
        char *command;
        os_error *err;

        err = next_nodename( env->test_search, &filename );

        if ( err )
        {
                wimpt_complain( err );
                return;
        }

        command = overflowing_malloc( strlen( "Filer_Run " ) + strlen( filename ) + 1 );

        if ( !command )
        {
                wimpt_complain( error( mb_malloc_failed ) );
                return;
        }

        sprintf( command, "Filer_Run %s", filename );

        overflowing_free( filename );

        wimpt_complain( os_cli( command ));

        overflowing_free( command );
}

static void view_object( action_environment *env )
{
        wimp_msgstr m;
        char *filename;
        os_error *err;

        err = next_nodename( env->test_search, &filename );

        if ( err )
        {
                wimpt_complain( err );
                return;
        }

        /*
                strrchr is guaranteed to work correctly due to the nature of the
                filename.
        */
        *strrchr( filename, '.' ) = '\0';

        m.hdr.size = 256;
        m.hdr.your_ref = 0;
        m.hdr.action = wimp_FilerOpenDir;
        m.data.words[ 0 ] = 0;
        m.data.words[ 1 ] = 0;
        strcpy( (char *)&m.data.words[2], filename );

        overflowing_free( filename );

        wimpt_complain( wimp_sendmessage( wimp_ESEND, &m, 0 ));
}

/*
     error Restart button
*/
static void restart_operation( action_environment *env )
{
#ifdef debugbut
        dprintf( "restart_operation: env=&%8X\n", (int)env );
#endif
        if ( env->action == Check_Full_Reading )
                restart_file_read();

        if ( env->action == Check_Empty_Writing )
                restart_file_write();

        switch_buttons( env, &abort_pause_buttons );
}

/*
     error Retry button
*/
static void retry_operation( action_environment *env )
{
        switch_buttons( env, &abort_pause_buttons );
}

/*
     This intercepts and handles the button events
*/
void button_event_handler( dbox db, void *handle )
{
        action_environment *env = handle;

        db = db; /* keep the compiler quiet */

        switch( dbox_get( env->status_box ))
        {
        case Abort_Button:
                env->button_actions.abort_action( env );
                break;

        case No_Skip_Button:
                env->button_actions.no_skip_action( env );
                break;

        case Yes_Retry_Button:
                env->button_actions.yes_retry_action( env );
                break;

        case Misc_Button:
                env->button_actions.misc_action( env );
                break;

        case Skip_Button:
                env->button_actions.skip_action( env );
                break;

        default:
                /* do nothing on other fields */
                break;
        }
}