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

#include "bbc.h"
#include "Global/FileTypes.h"
#include "Interface/HighFSI.h"

#include "swis.h"
#include "toolbox.h"
#include "colourdbox.h"
#include "fontdbox.h"
#include "saveas.h"
#include "event.h"
#include "window.h"
#include "wimp.h"
#include "wimplib.h"
#include "flex.h"

#include "main.h"
#include "msgtrans.h"
#include "pager.h"
#include "defines.h"
#include "ui.h"
#include "settings.h"
#include "colour.h"
#include "spritegen.h"
#include "watermark.h"

static int messages[]= {Wimp_MQuit,
                              Wimp_MDataLoad,
                              Wimp_MOpenConfigWindow,
                              0};

static int toolbox_events[]= {Toolbox_ObjectAutoCreated,
                              Toolbox_Error,
                              ActionButton_Selected,
                                   RadioButton_StateChanged,
                                   OptionButton_StateChanged,
                                   Adjuster_Clicked,
                                   WritableField_ValueChanged,
                                   StringSet_ValueChanged,
                                   NumberRange_ValueChanged,
                                   PopUp_AboutToBeShown,
//                                   ColourDbox_AboutToBeShown,
                                   ColourDbox_ColourSelected,
                                   FontDbox_ApplyFont,
                                   SaveAs_AboutToBeShown,
                                   SaveAs_SaveToFile,
                                   0};

static IdBlock id;

/* Main window display */

_kernel_oserror *error(_kernel_oserror *e, BOOL fatal)
{
  if (e==NULL) return NULL;

  wimp_report_error(e, 0, msgtrans("_TaskName") ,0,0,0);

  if (fatal) {
    exit(1);
  }

  return e;
}

static int message_quit(WimpMessage *msg,void *handle)
{
  BOOL *running=(BOOL *)handle;
  IGNORE(msg);
  *running=FALSE;

  if (settings_tried) {
    _swix(OS_CLI,_IN(0),"Filer_Run " PINSETUP_FILE);
    settings_tried=FALSE;
  }

  return 1;
}

static int message_dataload(WimpMessage *event, void *handle)
{
  pager *p=(pager *)handle;
  ObjectId page,object;
  ComponentId component;

  error(window_wimp_to_toolbox(0, event->data.data_load.destination_window, event->data.data_load.destination_icon, &object, &component), 0);

  page=pager_get_page(p,Page_Watermark);
  if (object==page || object==watermark_window) {
    if (event->data.data_load.file_type ==0xaff) {
      watermark_load_file(event->data.data_load.leaf_name,&edited_settings,page,TRUE);
    }
    return 1;
   }

  page=pager_get_page(p,Page_Background);

  if (object!=page/* || component!=BG_CustomImage*/) return 1;

  if ((event->data.data_load.file_type != 0xc85) && (event->data.data_load.file_type != 0xff9)) {
    if (!changefsi(&edited_settings,event->data.data_load.leaf_name)) return 1;
  }
  
  radiobutton_set_state(0, page, BG_Custom, 1);
  edited_settings.background_type=BACKDROP_CUSTOM;

  edited_settings.filetype=event->data.data_load.file_type;

  if (edited_settings.custom_image_filename) {
    flex_free((flex_ptr)&edited_settings.custom_image_filename);
    edited_settings.custom_image_filename=NULL;
  }
  if (flex_alloc((flex_ptr)&edited_settings.custom_image_filename,1+strlen(event->data.data_load.leaf_name))) {
    strcpy(edited_settings.custom_image_filename, event->data.data_load.leaf_name);
  }

  background_show_custom(&edited_settings,page);
  window_set_fades(Page_Background,page,&edited_settings);
 
  return 1;
}

static void task_init(BOOL *running)
{
  void *spritearea;

  error(toolbox_initialise(0, 310, messages, toolbox_events, "<PinSetup$Dir>", &msgtrans_block, &id, 0, NULL, &spritearea) ,TRUE);
  error(event_initialise(&id),TRUE);
  error(event_set_mask(Wimp_Poll_NullMask),FALSE);

  event_register_message_handler(Wimp_MQuit,message_quit,running);

  flex_init("PinSetup",(int *)&msgtrans_block,0);

  ui_init((int *)spritearea);
}


static int main_action(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  pager *p=(pager *)handle;

  switch (id->self_component) {
    case Action_Default:
      settings_set_default(&edited_settings);
      settings_update_windows(p,&edited_settings);
      break;

    case Action_Try:
      _swix(OS_CLI,_IN(0),"PinboardWatermark -off"); // as may not exist in PinSetup
      settings_try(&edited_settings);
      break;

    case Action_Cancel:
      if (settings_tried) {
        _swix(OS_CLI,_IN(0),"PinboardWatermark -off"); // as may not exist in PinSetup
        _swix(OS_CLI,_IN(0),"Filer_Run " PINSETUP_FILE);
        settings_tried=FALSE;
      }
      exit(0);  
      break;

    case Action_Set:
      if (settings_write(&current_settings,&edited_settings)) {
        if ((event->hdr.flags & ActionButton_Selected_Adjust)==0) {
          exit(0);
        }
      }
      break;

    case Action_Reset:
      settings_copy(&edited_settings,&current_settings);
      settings_update_windows(p,&edited_settings);
      break;
  }

  return 1;
}

static int toolbox_autocreated(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  ToolboxObjectAutoCreatedEvent *e=(ToolboxObjectAutoCreatedEvent *)event;
  pager *p=(pager *)handle;

  if (strcmp(e->template_name,"SaveSticky")==0) {
    event_register_toolbox_handler(id->self_id,SaveAs_AboutToBeShown,sticky_saveshow,&edited_settings);
    event_register_toolbox_handler(id->self_id,SaveAs_SaveToFile,sticky_savetofile,&edited_settings);
    return 1;
  }

  if (strcmp(e->template_name,"SaveStore")==0) {
    event_register_toolbox_handler(id->self_id,SaveAs_AboutToBeShown,storage_saveshow,&edited_settings);
    event_register_toolbox_handler(id->self_id,SaveAs_SaveToFile,storage_savetofile,&edited_settings);
    return 1;
  }

  if (strcmp(e->template_name,"ButtonBar")==0) {
    event_register_toolbox_handler(id->self_id,ActionButton_Selected,main_action,p);
    return 1;
  }

  return 0;
}

static int message_open_config(WimpMessage *m,void *handle)
{
  // reopen configure window at top of stack
  pager *p=(pager *)handle;
  WimpGetWindowStateBlock state;

  if (window_get_wimp_handle(0,p->parent,&state.window_handle)) return 0;

  if (wimp_get_window_state(&state)==NULL) {
    state.behind=-1; // move to top of stack
    toolbox_show_object(0,p->parent,Toolbox_ShowObject_FullSpec,&state.visible_area.xmin,0,0);
  }

  return 1;
}

static int wimp_keypress(int e,WimpPollBlock *poll,IdBlock *id,void *handle)
{
  switch (poll->key_pressed.key_code) {
    case 0x1b:
      if (settings_tried) {
        _swix(OS_CLI,_IN(0),"Filer_Run " PINSETUP_FILE);
        settings_tried=FALSE;
      }
      exit(0);

    default:
      // pass on any unhandled keycodes
      wimp_process_key(poll->key_pressed.key_code);
  }

  return 1;
}

static ObjectId windows_init(pager **p)
{
  ObjectId mainh,backgroundh,pinappearh,pinarrangeh,stickyh,storageh,waterh,misch;
  ObjectId fonth;

  watermark_init();

  error(toolbox_create_object(0,"Main",&mainh),TRUE);
  error(toolbox_create_object(0,"Background",&backgroundh),TRUE);
  error(toolbox_create_object(0,"PinAppear",&pinappearh),TRUE);
  error(toolbox_create_object(0,"PinArrange",&pinarrangeh),TRUE);
  error(toolbox_create_object(0,"Stickies",&stickyh),TRUE);
  error(toolbox_create_object(0,"Storage",&storageh),TRUE);
  error(toolbox_create_object(0,"Watermark",&waterh),TRUE);
  error(toolbox_create_object(0,"Misc",&misch),TRUE);

  error(toolbox_create_object(0,"StickyFont",&fonth),TRUE);

  *p=pager_init(mainh, 12,12,800,128, pager_callback, 7,
                Page_Background,backgroundh,
                Page_PinAppear,pinappearh,
                Page_PinArrange,pinarrangeh,
                Page_Sticky,stickyh,
                Page_Storage,storageh,
                Page_Watermark,waterh,
                Page_Misc,misch);

  if (*p==NULL) {
    msgtrans_error("NoMem");
    exit(1);
  }

  colour_init();
  stringset_init(&edited_settings);

  event_register_toolbox_handler(-1,Toolbox_ObjectAutoCreated,toolbox_autocreated,*p);

  // background page
  event_register_toolbox_handler(backgroundh,RadioButton_StateChanged,background_radioclick,&edited_settings);
  event_register_toolbox_handler(backgroundh,OptionButton_StateChanged,background_optionclick,&edited_settings);
  event_register_toolbox_handler(backgroundh,Adjuster_Clicked,background_adjusterclick,&edited_settings);

  colour_add(backgroundh,BG_BGcolour,BG_BGcolourmenu,&edited_settings.background_colour);

  // pin appearance page
  event_register_toolbox_handler(pinappearh,RadioButton_StateChanged,appearance_radioclick,&edited_settings);
  colour_add(pinappearh,PA_TextColour,PA_TextColourMenu,&edited_settings.icon_text_colour);
  colour_add(pinappearh,PA_OutlineColour,PA_OutlineMenu,&edited_settings.outline_colour);
  stringset_add(Page_PinAppear,pinappearh,PA_Size,iconsize_strings,(int *)&edited_settings.iconsize);

  // pin arrange page
  event_register_toolbox_handler(pinarrangeh,OptionButton_StateChanged,arrange_optionclick,&edited_settings);
  stringset_add(Page_PinArrange,pinarrangeh,PA_Iconize,iconize_strings,(int *)&edited_settings.iconize_dest);
  stringset_add(Page_PinArrange,pinarrangeh,PA_IconStack,stack_strings,(int *)&edited_settings.iconize_stack);
  stringset_add(Page_PinArrange,pinarrangeh,PA_Tidy,tidy_strings,(int *)&edited_settings.tidy_dest);
  stringset_add(Page_PinArrange,pinarrangeh,PA_TidyStack,stack_strings,(int *)&edited_settings.tidy_stack);

  // stickies page
  event_register_wimp_handler(stickyh,Wimp_EMouseClick,sticky_fontshow,(void *)fonth);
  event_register_toolbox_handler(fonth,FontDbox_ApplyFont,sticky_fontset,&edited_settings);
  event_register_toolbox_handler(stickyh,WritableField_ValueChanged,writable_changed,&edited_settings.sticky_filename);

  // storage page
  event_register_toolbox_handler(storageh,WritableField_ValueChanged,writable_changed,&edited_settings.savedfiles_path);
  stringset_add(Page_Storage,storageh,SF_Autosave,autosave_strings,(int *)&edited_settings.autosave);
  stringset_add(Page_Storage,storageh,SF_Overwrite,overwrite_strings,(int *)&edited_settings.overwrite);

  // watermark page
  event_register_toolbox_handler(waterh,OptionButton_StateChanged,watermark_optionclick,&edited_settings);
  event_register_toolbox_handler(waterh,RadioButton_StateChanged,watermark_radioclick,&edited_settings);
  event_register_toolbox_handler(waterh,NumberRange_ValueChanged,watermark_offsetchange,&edited_settings);

  // misc page
  event_register_toolbox_handler(misch,OptionButton_StateChanged,misc_optionclick,&edited_settings);

  // main window


  event_register_wimp_handler(-1,Wimp_EKeyPressed,wimp_keypress,NULL);
  event_register_message_handler(Wimp_MDataLoad,message_dataload,*p);
  event_register_message_handler(Wimp_MOpenConfigWindow,message_open_config,*p);

  return mainh;
}

static void configure_show(ObjectId mainh,int *openat,pager *p)
{
  if (openat[0]==-1) {
    error(toolbox_show_object(0,mainh,Toolbox_ShowObject_Centre,NULL,0,0),FALSE);
  } else {
    error(toolbox_show_object(0,mainh,Toolbox_ShowObject_TopLeft,openat,0,0), FALSE);
  }

  pager_show(p,0);
}

int main(int argc, char *argv[])
{
  BOOL running=TRUE;
  WimpPollBlock pollblock;
  int event_code;
  int openat[2]={-1,-1};
  ObjectId mainh;
  pager *p;

  /* Have we been passed any co-ordinates to open at? */
  if ((argc >= 4) && (strcmp(argv[1], "-openat") == 0)) {
    openat[0] = atoi(argv[2]);
    openat[1] = atoi(argv[3]);
  }

  task_init(&running);

  mainh=windows_init(&p);

  settings_init(p);

  configure_show(mainh,openat,p);

  while (running) {
    event_poll(&event_code, &pollblock, NULL);
  }

  return 0;
}
