/*
 * main.c
 * ------
 * 15/9/2025
 */

#include "wimp.h"
#include "main.h"
#include "lib.h"

const char appname[] = "Activity";

// iconbar menu
static menu_t iconbar_menu =
{
  "Activity",NULL,7, 7,2,7,0,0,44,0,
  {
    {256,-1,IC_DEF,"Info",       NULL,4},
    {  0,-1,IC_DEF,"Help...",    NULL,7},
    {128,-1,IC_DEF,"Quit",       NULL,4}
  }
};
#define ICONBAR_MENU_ITEMS 3

ro_t ro;


/*
 * read_menus
 * ----------
 * load menu text from Messages file if possible
 */
static void read_menus(void)
{
  static char menu_strings[256]; // holds all menu strings
  char *s = menu_strings;

  s = msg_load_menu("iconbar_m", s, &iconbar_menu);

  iconbar_menu.item[0].sub = ro.win_data[WIN_INFO].win_handle;
}


/*
 * mouse_click
 * -----------
 */
static void mouse_click(int blk[])
{
  // iconbar
  if(blk[3] == ICONBAR)
  {
    switch(blk[2])
    {
      case MOUSE_SELECT:
        open_window(WIN_MAIN);
        break;

      case MOUSE_MENU:
        open_menu(blk[0] - 64, (44*ICONBAR_MENU_ITEMS)+96, MENU_ICONBAR, (int)&iconbar_menu);
        break;
    }
    return;
  }
}


/*
 * menu_selection
 * --------------
 */
static void menu_selection(int blk[])
{
  int b[5];
  _kernel_swi_regs regs;

  regs.r[1] = (int)b;
  _kernel_swi(Wimp_GetPointerInfo, &regs, &regs);

  switch(ro.cur_menu)
  {
    case MENU_ICONBAR:
      switch(blk[0])
      {
        case 1: // help
          _kernel_oscli("Filer_Run <ActivityRes$Dir>.Help");
          break;

        case 2: // quit
          ro.flags |= 1<<QUIT;
          break;
      }
      if(b[2] == 1) // adjust
        open_menu(0, 0, MENU_ICONBAR, (int)&iconbar_menu);
      break;
  }
}


/*
 * msg_help
 * --------
 * Supplies help text. Requires the HelpRequest message block and current menu tag.
 */
static void msg_help(int *b, int cur_menu)
{
  _kernel_swi_regs regs;
  int blk[10], ok = 0;

  if(b[8] == ICONBAR)
    ok = msg_lookup("iconbar_wh", -1, (char *)&b[5]);

  // Main window
  else if(b[8] == ro.win_data[WIN_MAIN].win_handle)
  {
    if((ok = msg_lookup("main_wh", b[9], (char *)&b[5])) == 0)
      ok = msg_lookup("main_wh", -1, (char *)&b[5]);
  }

  // Info window
  else if(b[8] == ro.win_data[WIN_INFO].win_handle)
    ok = msg_lookup("info_wh", -1, (char *)&b[5]);

  // unknown window, check for a menu
  else if(b[8] != -2)
  {
    regs.r[0] = 1;
    regs.r[1] = (int)blk;
    regs.r[2] = b[8]; // window handle
    regs.r[3] = b[9]; // icon handle
    _kernel_swi(Wimp_GetMenuState, &regs, &regs);
    switch(cur_menu)
    {
      case MENU_ICONBAR:
        ok = msg_lookup("iconbar_mh", blk[0], (char *)&b[5]);
        break;
    }
  }

  if(!ok)
    return; // no help available

  // send help text to Help application
  regs.r[0] = 17;     // User message
  regs.r[1] = (int)b;
  regs.r[2] = b[1];   // sender task handle
  b[0] = 256; // buffer length
  b[3] = b[2];
  b[4] = MESSAGE_HELPREPLY;
  _kernel_swi(Wimp_SendMessage, &regs, &regs);
}


/*
 * wimp_msg
 * --------
 * Handles all messages
 */
static void wimp_msg(int blk[], int msg)
{
//  _kernel_swi_regs regs;
//  int err;

  switch (blk[4]) // message action
  {
    case MESSAGE_QUIT:
      ro.flags |= 1<<QUIT;
      break;

    case MESSAGE_HELPREQUEST:
      msg_help(blk, ro.cur_menu);
      break;
  }
}


/*
 * loadtemplates
 * -------------
 */
static int loadtemplates(const char * filename)
{
  const struct template_s
  {
    const char *name;
    int spr; // true if sprites required
  } tmpl[NUM_WINDOWS] =
  { {"Info",0},
    {"Main",1}
  };
  _kernel_swi_regs regs;
  int *sprites, i, err = 0;

  regs.r[0] = READ_CATINFO;
  regs.r[1] = (int)filename;
  _kernel_swi(OS_FILE,&regs,&regs);
  if(regs.r[0] != IS_FILE)
    err = CANNOT_OPEN_TEMPLATES_FILE;
  else
  {
    regs.r[1] = (int)filename;
    _kernel_swi(Wimp_OpenTemplate, &regs, &regs);

    if((sprites = loadsprites("<Activity$Dir>.Sprites")) == 0)
      err = CANNOT_OPEN_SPRITES_FILE;
    else
      for(i=0; i<NUM_WINDOWS; i++)
        if((ro.win_data[i].win_handle = loadtemplate(tmpl[i].name, (tmpl[i].spr) ? sprites : 0)) == 0)
        {
          err = INFO_TEMPLATE_NOT_FOUND + i; // Cannot find template
          break;
        }
    _kernel_swi(Wimp_CloseTemplate, &regs, &regs);
  }

  return err;
}


/*
 * terminate_app
 * -------------
 */
static void terminate_app(void)
{
  _kernel_swi_regs regs;

  if(ro.flags & (1<<MESSAGES_OPEN))
    msg_close();

  remove_driver();

  regs.r[0] = ro.task_handle;
  regs.r[1] = *(int *)"TASK";
  _kernel_swi(Wimp_CloseDown, &regs, &regs);
}


/*
 * main
 * ----
 * Main Wimp Poll loop.
 */
int main(void)
{
  _kernel_swi_regs regs;
  int err, blk[64];
  int msglist[] = {0};

  // exit if we are already running
  regs.r[0] = 0;
  while(regs.r[0] >= 0)
  {
    regs.r[1] = (int)blk;
    regs.r[2] = 4*sizeof(int);
    _kernel_swi(TaskManager_EnumerateTasks, &regs, &regs);
    if(strcmp((char *)blk[1], appname) == 0)
      return 0;
  }

  regs.r[0] = 350;
  regs.r[1] = *(int *)"TASK";
  regs.r[2] = (int)appname;
  regs.r[3] = (int)msglist;
  _kernel_swi(Wimp_Initialise, &regs, &regs);
  ro.task_handle = regs.r[1];

  // create iconbar icon
  blk[0] = -1; // r/h icon
  blk[1] = 0;
  blk[2] = 0;
  blk[3] = 68;
  blk[4] = 68;
  blk[5] = 0x0000301a;
  strcpy((char *)&blk[6], "!activity");
  regs.r[0] = 0;
  regs.r[1] = (int)blk;
  _kernel_swi(Wimp_CreateIcon, &regs, &regs);

  atexit(terminate_app);

  if(!msg_open("<ActivityRes$Dir>.Messages"))
    report_error("Cannot open messages file", 1);
  else
  {
    ro.flags |= (1<<MESSAGES_OPEN);
    read_vdu_vars();

    if((err = loadtemplates("<ActivityRes$Dir>.Templates")) != 0)
      report_error_number(err, 1);
    else
    {
      ro.flags |= (1<<TEMPLATES_OK);
      read_menus();
      create_driver();

      while ((ro.flags & (1<<QUIT)) == 0)
      {
        _kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
        regs.r[2] = regs.r[0] + 10;
        regs.r[0] = 0x3830; // poll mask
        regs.r[1] = (int)blk;
        _kernel_swi(Wimp_PollIdle, &regs, &regs);
        switch (regs.r[0]) // result
        {
          case 0: midi_in_port(); break; // null reason
          case 2: _kernel_swi(Wimp_OpenWindow, &regs, &regs); break;
          case 3: _kernel_swi(Wimp_CloseWindow, &regs, &regs); break;
          case 6: mouse_click(blk); break;
          case 9: menu_selection(blk); break;
          case 17:
          case 18:
          case 19: wimp_msg(blk, regs.r[0]); break;
        }
      }
    }
  }

  return 0;
}

