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

#include "ctype.h"
#include "toolbox.h"
#include "event.h"
#include "gadgets.h"
#include "utils.h"
#include "vars.h"
#include "aspi.h"
#include "miscfile.h"

static int  aspi_card_selected=0, cards=0;

static int  aspi_window_optionbutton(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  int x;
  NotUsed (handle);
  NotUsed (event);
  NotUsed (event_code);

  if (id_block->self_component == ASPI_RESTRICT ||
      id_block->self_component == ASPI_64K)
    return(1);

  x=id_block->self_component;

  if (id_block->self_component >= ASPI_IGNOREBASE && id_block->self_component < ASPI_IGNOREBASE+8) x-=ASPI_IGNOREBASE;
  else if (id_block->self_component >= ASPI_RESERVEBASE && id_block->self_component < ASPI_RESERVEBASE+8) x-=ASPI_RESERVEBASE;
  else if (id_block->self_component >= ASPI_FORCEBASE && id_block->self_component < ASPI_FORCEBASE+8) x-=ASPI_FORCEBASE;

  if (id_block->self_component != ASPI_IGNOREBASE+x)
    optionbutton_set_state(0,aspi_window,ASPI_IGNOREBASE+x,0);
  if (id_block->self_component != ASPI_RESERVEBASE+x)
    optionbutton_set_state(0,aspi_window,ASPI_RESERVEBASE+x,0);
  if (id_block->self_component != ASPI_FORCEBASE+x)
    optionbutton_set_state(0,aspi_window,ASPI_FORCEBASE+x,0);
  return (1);
}

extern void setup_aspi_window(void)
{
  raise_error(toolbox_show_object(0,aspi_window,0,0,0,0));
  tmp_config.aspi = config.aspi;
  raise_error(numberrange_set_value(0, aspi_window, ASPI_CARDNUM, 0));
  aspi_card_selected = 0;
  update_aspi_window();
}

static void update_aspi_devices(void)
{
  int  x;
  char b[256], *s;

  hourglass_on();
  for(x=0; x!=8; x++)
  {
    //fprintf(stderr, "scsi_status(%d) = %d\n", (aspi_card_selected<<3)+x,scsi_status((aspi_card_selected<<3)+x));
    raise_error(displayfield_set_value(0, aspi_window, ASPI_DISPBASE+x, "???"));
    if ( scsi_initialise (( aspi_card_selected << 3 ) + x, b, 256) == 0 )
    {
      for ( s = b; *s != 0; s++ ) if ( *s == 9 ) *s = 32;
      /* skip device id */
      s = b;
      while (( *s != 0 ) && ( *s < 'A' )) s++;
    }
    else
    {
      b [ 0 ] = 0;
      s = b;
    }
    raise_error(displayfield_set_value( 0, aspi_window, ASPI_DISPBASE+x, s ));
  }
  hourglass_off();
}

#define ASPI_BIT ((1<<x)<<(aspi_card_selected<<3))

extern void update_aspi_window(void)
{
  int x;

  for (x=0; x!=8; x++)
  {
    raise_error(optionbutton_set_state(0, aspi_window, ASPI_IGNOREBASE+x, ((tmp_config.aspi.ignore & ASPI_BIT) != 0)));
    raise_error(optionbutton_set_state(0, aspi_window, ASPI_RESERVEBASE+x, ((tmp_config.aspi.reserve & ASPI_BIT) != 0)));
    raise_error(optionbutton_set_state(0, aspi_window, ASPI_FORCEBASE+x, ((tmp_config.aspi.force & ASPI_BIT) != 0)));
  }
  //fprintf(stderr, "aspibuffer = %d", tmp_config.aspi.aspibuffer);
  raise_error(optionbutton_set_state(0,aspi_window,ASPI_RESTRICT,tmp_config.aspi.aspibuffer & 1));
  raise_error(optionbutton_set_state(0,aspi_window,ASPI_64K,(tmp_config.aspi.aspibuffer & 2)!=0));
  update_aspi_devices();
}

static void aspi_read_tmp_config(void)
{
  int x, v;

  tmp_config.aspi.ignore  &= ~(0xff<<(aspi_card_selected<<3));
  tmp_config.aspi.reserve &= ~(0xff<<(aspi_card_selected<<3));
  tmp_config.aspi.force   &= ~(0xff<<(aspi_card_selected<<3));

  for (x=0; x!=8; x++)
  {
    raise_error(optionbutton_get_state(0,aspi_window,ASPI_IGNOREBASE+x,&v));
    if (v) tmp_config.aspi.ignore |= ASPI_BIT;
    raise_error(optionbutton_get_state(0,aspi_window,ASPI_RESERVEBASE+x,&v));
    if (v) tmp_config.aspi.reserve |= ASPI_BIT;
    raise_error(optionbutton_get_state(0,aspi_window,ASPI_FORCEBASE+x,&v));
    if (v) tmp_config.aspi.force |= ASPI_BIT;
  }
}

extern int aspi_window_click_handler(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  int v1, v2;
  NotUsed (handle);
  NotUsed (event);
  NotUsed (event_code);

  if (id_block->self_component == ASPI_SCAN)
    update_aspi_devices();
  if (id_block->self_component == ASPI_OK)
  {
    raise_error(optionbutton_get_state(0,aspi_window,ASPI_RESTRICT,&v1));
    raise_error(optionbutton_get_state(0,aspi_window,ASPI_64K,&v2));
    tmp_config.aspi.aspibuffer = v1 | (v2<<1);
    aspi_read_tmp_config();
    check_for_modified_data((int)&config.aspi, (int)&tmp_config.aspi, sizeof(config.aspi));
    config.aspi = tmp_config.aspi;
  }

  return(1);
}

static int  aspi_window_numberrange(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  NotUsed (handle);
  NotUsed (id_block);
  NotUsed (event);
  NotUsed (event_code);

  aspi_read_tmp_config();
  raise_error(numberrange_get_value(0, aspi_window, ASPI_CARDNUM, &aspi_card_selected));
  update_aspi_window();
  return (1);
}

extern int do_aspi_initialise(void)
{
  int i, j, position;
  char b[256], *p;

  raise_error(event_register_toolbox_handler(aspi_window, ActionButton_Selected, aspi_window_click_handler, 0));
  raise_error(event_register_toolbox_handler(aspi_window, OptionButton_StateChanged, aspi_window_optionbutton, 0));
  raise_error(event_register_toolbox_handler(aspi_window, NumberRange_ValueChanged, aspi_window_numberrange, 0));

  /* detect no. of SCSI cards by probing possible host numbers */
  cards = 0;
  for ( i = 0; i <= 3; i++ )
  {
    if ( cards < i )  break;
    for ( j = 7; j >= 0; j-- )
    {
      if ( cards > i )  break;
      if ( scsi_initialise (( i << 3 ) + j, b, 256) == 0 )
      {
        if ( strlen ( b ) > 10 )
        {
          /* convert enumeration string to lower case letters and search for 'host' */
          for ( p = b; p <= b + 20; p++ )
          {
            *p = (char)tolower ( (int)*p );
          }
          position = (int)(strstr ( b, "host" )) - (int)b;
          if ( position > 0 && position <= 16 )
          {
            /* add one SCSI Card */
            cards++;
          }
        }
      }
    }
  }
  if (cards == 0) return (1);
  raise_error(numberrange_set_bounds(2, aspi_window, ASPI_CARDNUM, 0, cards-1, 1, 0));
  return(0);
}
