#include <stdio.h>
#include <stdlib.h>
#include "kernel.h"
#include "swis.h"

#include "toolbox.h"
#include "event.h"
#include "wimp.h"
#include "wimplib.h"
#include "window.h"

#include "base.h"
#include "toggle.h"
#include "pinboard.h"
#include "bbc.h"

#include "debug.h"

static ObjectId toggle_win=0;

static void toggle_hide_prompt(_backdrop_state *state);

static void toggle_set_position(_backdrop_state *state)
{
  // update the backdrop window position
  WimpGetWindowStateBlock win;
  window_get_wimp_handle(0,state->obj,&win.window_handle);
  wimp_get_window_state(&win);

  // we need to adjust the window stack that the pinboard is on
  switch (state->toggle_position) {
    case TOGGLE_FRONT:
      win.flags&=~(1<<11);
      win.behind=-1;
      break;

    case TOGGLE_BACK:
      win.flags|=(1<<11);
      win.behind=-2;
      break;
   }

//  win.behind=-state->toggle_position;
//  wimp_open_window((WimpOpenWindowBlock *)&win);
  _swix(Wimp_OpenWindow,_INR(1,4),&win,0x4b534154,-1,1);
}

static int toggle_lose_caret(int event_code,WimpPollBlock *poll,IdBlock *id,void *handle)
{
  _backdrop_state *state=(_backdrop_state *)handle;

  state->toggle_position=TOGGLE_BACK;
  toggle_set_position(state);
  toggle_hide_prompt(state);

  return 1; 
}

static int toggle_send_to_back(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  _backdrop_state *state=(_backdrop_state *)handle;

  state->toggle_position=TOGGLE_BACK;
  toggle_set_position(state);
  toggle_hide_prompt(state);

  return 1;
}

static void toggle_hide_prompt(_backdrop_state *state)
{
  if (!toggle_win) return;

  event_deregister_toolbox_handler(toggle_win,ActionButton_Selected,toggle_send_to_back,state);
  event_deregister_wimp_handler(toggle_win,Wimp_ELoseCaret,toggle_lose_caret,state);

  toolbox_delete_object(0,toggle_win);
  toggle_win=0;
}

static void toggle_show_prompt(_backdrop_state *state)
{
  _kernel_oserror *e;
  BBox extent;
  int coords[2];

  if (!toggle_win) {
    e=toolbox_create_object(0,"toggle",&toggle_win);
    if (e) return; // absorb the error and carry on

    // add handlers
    event_register_toolbox_handler(toggle_win,ActionButton_Selected,toggle_send_to_back,state);
    event_register_wimp_handler(toggle_win,Wimp_ELoseCaret,toggle_lose_caret,state);
  }

  // display over icon bar
  if (window_get_extent(0,toggle_win,&extent)) {
    coords[0]=8;
    coords[1]=72;
  } else {
    int w=extent.xmax-extent.xmin;
    int h=extent.ymax-extent.ymin;
    coords[0]=(bbc_modevar(-1,bbc_XWindLimit)*(1<<bbc_modevar(-1,bbc_XEigFactor))-w)/2;
    coords[1]=h+(ICONBAR_HEIGHT-h)/2;
  }
  toolbox_show_object(0,toggle_win,2,coords,0,0);
}

int message_togglebd(WimpMessage *msg,void *handle)
{
  WimpToggleBackdropMessage *m=(WimpToggleBackdropMessage *)msg;
  _backdrop_state *state=(_backdrop_state *)handle;

  if (m->flags<0 || m->flags>3) return 0;

  if (m->flags!=3) {
    // do something to the backdrop
    if (m->flags==0) {
      state->toggle_position=3-state->toggle_position; 
    } else {
      state->toggle_position=m->flags;
    }

    toggle_set_position(state);
  }

  if (state->toggle_position==TOGGLE_FRONT) {
    toggle_show_prompt(state);
  } else {
    toggle_hide_prompt(state);
  }

  // send state back to caller
  if (m->hdr.sender!=taskhandle) {
    m->flags=state->toggle_position;
    wimp_send_message(17,m,m->hdr.sender,0,NULL);
  }

  return 1;
}
