/* pager */

/* provide a pager/tab system */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

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

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

#include "main.h"
#include "pager.h"

static int pager_radio(int event_code,ToolboxEvent *event,IdBlock *id,void *handle)
{
  pager *p=(pager *)handle;
  RadioButtonStateChangedEvent *e=(RadioButtonStateChangedEvent *)event;
  int i;

  if (e->state==0) return 1;

  for (i=0;i<p->children;i++) {
    if (p->child[i].button==id->self_component) {
      pager_show(p,i);
      return 1;
    }
  }

  return 0; // in case someone else wants a look
}

void pager_show(pager *p,int index)
{
  WindowShowObjectBlock show;
  WimpGetWindowStateBlock state;
  BBox extent;

  // attach the given child
  if (index<0 || index>=p->children) return;

  // hide current child
  if (p->current_child) {
    toolbox_hide_object(0,p->current_child);
  }

  p->current_child=p->child[index].child;

  window_get_extent(0,p->parent,&extent);
  window_get_wimp_handle(0,p->parent,&state.window_handle);
  wimp_get_window_state(&state);

  show.visible_area.xmin=p->x_offset + state.visible_area.xmin - state.xscroll;
  show.visible_area.xmax=show.visible_area.xmin+p->width;
  show.visible_area.ymax=state.visible_area.ymax - state.yscroll - p->y_offset_top;
  show.visible_area.ymin=state.visible_area.ymin - state.yscroll + p->y_offset_bottom;
  show.xscroll=0;
  show.yscroll=0;
  show.behind=-1;
  show.window_flags=0;
  window_get_wimp_handle(0,p->parent,&show.parent_window_handle);
  show.alignment_flags=0;

  toolbox_show_object(Toolbox_ShowObject_AsSubWindow,p->child[index].child,Toolbox_ShowObject_FullSpec,&show,p->parent,0);

  if (p->pager_paged) {
    p->pager_paged(p->child[index].button,p->child[index].child);
  }
}

int pager_open(int event_code,WimpPollBlock *block,IdBlock *id,void *handle)
{
  pager *p=(pager *)handle;
  WimpGetWindowStateBlock state;
  WindowShowObjectBlock show;
  int height,parent_height;
  
  height=block->open_window_request.visible_area.ymax-block->open_window_request.visible_area.ymin;
  block->open_window_request.visible_area.xmax=block->open_window_request.visible_area.xmin+p->width;
  wimp_open_window(&block->open_window_request);

  // adjust parent to match
  window_get_wimp_handle(0,p->parent,&state.window_handle);
  wimp_get_window_state(&state);

  parent_height=state.visible_area.ymax-state.visible_area.ymin;
  if (parent_height!=height+p->y_offset_top+p->y_offset_bottom) {
    show.visible_area.xmin=state.visible_area.xmin;
    show.visible_area.ymin=state.visible_area.ymax-height-p->y_offset_top-p->y_offset_bottom;
    show.visible_area.xmax=state.visible_area.xmax;
    show.visible_area.ymax=state.visible_area.ymax;
    show.xscroll=state.xscroll;
    show.yscroll=state.yscroll;
    show.behind=state.behind;
//    wimp_open_window((WimpOpenWindowBlock *)&state);

    toolbox_show_object(0,p->parent,Toolbox_ShowObject_FullSpec,&show,0,0);
  }

  return 1;
}

pager *pager_init(ObjectId parent, int x, int ytop, int w, int ybottom, void (*callback)(ComponentId,ObjectId), int children, ...)
{
  // pass parent, children and then a list of [button/child obj] pairs

  // creates a pager and harmonises the window vertical extents as need be

  pager *p=(pager *)malloc(sizeof(pager)+children*sizeof(_page_child));
  int i,max_height=0;
  BBox extent;
  va_list ap;
  va_start(ap,children);

  if (p==NULL) return NULL;

  p->parent=parent;
  p->x_offset=x;
  p->y_offset_top=ytop;
  p->width=w;
  p->y_offset_bottom=ybottom;
  
  p->pager_paged=callback;

  p->children=children;
  p->current_child=0;

  for (i=0;i<children;i++) {
    p->child[i].button=va_arg(ap,ComponentId);
    p->child[i].child=va_arg(ap,ObjectId);
    window_get_extent(0,p->child[i].child,&extent);
    if (extent.ymax-extent.ymin>max_height) max_height=extent.ymax-extent.ymin;
    error(event_register_wimp_handler(p->child[i].child,Wimp_EOpenWindow, pager_open, p),TRUE);
  }  

  // apply the extent to parent
  window_get_extent(0,parent,&extent);
  extent.ymin=extent.ymax-max_height-ytop-ybottom;
  window_set_extent(0,parent,&extent);

  // and then the children
  for (i=0;i<children;i++) {
    window_get_extent(0,p->child[i].child,&extent);
    extent.ymin=extent.ymax-max_height;
    window_set_extent(0,p->child[i].child,&extent);
  }

  error(event_register_toolbox_handler(parent, RadioButton_StateChanged, pager_radio, p),TRUE);


  // show the first child immediately
  pager_show(p,0);

  va_end(ap);

  return p;
}

ObjectId pager_get_page(pager *p,ComponentId c)
{
  int i;
  for (i=0;i<p->children;i++) {
    if (p->child[i].button==c) return p->child[i].child;
  }
  return -1;
}
