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

#include "kernel.h"
#include "swis.h"

#include "toolbox.h"
#include "colourdbox.h"
#include "gadgets.h"
#include "flex.h"
#include "event.h"
#include "wimp.h"
#include "wimplib.h"

#include "msgtrans.h"
#include "colour.h"
#include "main.h"

static swatch *_swatches=NULL;
static int _swatch_count=0;
static ObjectId _colourdbox=0;

static void _colour_show(int index)
{
  // update the display for this colour
  char valid[16];
  char colourstring[8];
  char *ptr;

  sprintf(colourstring,"%06x",*(_swatches[index].dest)>>8);
  button_get_validation(0,_swatches[index].win,_swatches[index].display,valid,16,NULL);
  if ((ptr=strstr(valid,"C/"))!=NULL) {
    memcpy(ptr+2,colourstring,6);
  }
  button_set_validation(0,_swatches[index].win,_swatches[index].display,valid);
}

void colour_show(ObjectId win,ComponentId c)
{
  // ensure up-to-date from the settings
  int i;
  for (i=0;i<_swatch_count;i++) {
    if (_swatches[i].win==win && _swatches[i].display==c) {
      _colour_show(i);
      return;
    }
  }
}

static int colour_selected(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  int index;
  ColourDboxColourSelectedEvent *e=(ColourDboxColourSelectedEvent *)event;

  for (index=0;index<_swatch_count;index++) {
    if (_swatches[index].win==id->parent_id && _swatches[index].popup==id->parent_component) {
      *(_swatches[index].dest)=e->colour_block[0];
      _colour_show(index);
      return 1;
    }
  }

  return 0;
}

void colour_add(ObjectId win,ComponentId display,ComponentId popup,unsigned int *dest)
{
  if (_swatches) {
    if (!flex_extend((flex_ptr)&_swatches,(_swatch_count+1)*sizeof(swatch))) {
      msgtrans_error("NoMem");
      exit(1);
    }
  } else {
    if (!flex_alloc((flex_ptr)&_swatches,sizeof(swatch))) {
      msgtrans_error("NoMem");
      exit(1);
    }
  }

  _swatches[_swatch_count].win=win;
  _swatches[_swatch_count].display=display;
  _swatches[_swatch_count].popup=popup;
  _swatches[_swatch_count].dest=dest;

  _swatch_count++;
}

static int colourpopup_show(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  int colour_block[2];
  int index;
  IGNORE(event);
//  PopUpAboutToBeShownEvent *e=(PopUpAboutToBeShownEvent *)event;

  BBox gadgetbox;
  TopLeft tl;
  WimpGetWindowStateBlock winstate;

  for (index=0;index<_swatch_count;index++) {
    if (_swatches[index].win==id->self_id && _swatches[index].popup==id->self_component) {
      // found it!
      colour_block[0]=*(_swatches[index].dest);
      colour_block[1]=0;
      colourdbox_set_colour(0,_colourdbox,colour_block);

      // event block contains invalid coords, so we need to roll our own :(
      window_get_wimp_handle(0,id->self_id,&winstate.window_handle);
      wimp_get_window_state(&winstate);
      gadget_get_bbox(0,id->self_id,id->self_component,&gadgetbox);
      tl.x=gadgetbox.xmax + winstate.visible_area.xmin - winstate.xscroll;
      tl.y=gadgetbox.ymax + winstate.visible_area.ymax - winstate.yscroll;

      toolbox_show_object(Toolbox_ShowObject_AsMenu,_colourdbox,Toolbox_ShowObject_TopLeft,&tl,id->self_id,id->self_component);
    }
  }


  return 0; // allow other popup actions
}

void colour_init(void)
{
  error(toolbox_create_object(0,"Colour",&_colourdbox),TRUE);
  event_register_toolbox_handler(_colourdbox,ColourDbox_ColourSelected,colour_selected,NULL);

  event_register_toolbox_handler(-1,PopUp_AboutToBeShown,colourpopup_show,NULL);
}
