// Copyright 1998 Acorn Computers Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "walkth.h"
#include "error.h"
#include "main.h"
#include "kernel.h"
#include <ctype.h>

stage::stage()
{
  limits.xmin = 0;
  limits.xmax = 0;
  limits.ymin = 0;
  limits.ymax = 0;

  file_name = NULL;
  help_text = NULL;
}

stage::~stage()
{
  delete help_text;
  delete file_name;
}

int
stage::zero_area(void)
{
  return (!( limits.xmin | limits.xmax | limits.ymin | limits.ymax ));
}


void
stage::set_stage(char *text, int *counter, int max_val)
{
  // this file scans an array for;
  //	char *file_name;
  //	BBox 4 box values and converts these from mm to os units.
  //    char *help text;
  // this comprises one stage.

  int count = (*counter), string_count;
  // file_name
  while  ((count < max_val)&&(!isalnum(text[count]))) count++;
  if (count < max_val) {
    	string_count = count;
  	while (isalnum(text[count])) count++;
  }
  if (count < max_val) {
  	file_name = new char[(count - string_count)+1];
  	strncpy(file_name, (text+string_count), (count - string_count));
  	file_name[count - string_count] = NULL;
  }
  // BBox
  while ((count < max_val)&&(!isdigit(text[count]))) count++;
  if (count < max_val) limits.xmin = (int)(MM_OSUNIT * atof(text+count));
  while ((count < max_val)&&(isdigit(text[count]))) count++;

  while  ((count < max_val)&&(!isdigit(text[count]))) count++;
  if (count < max_val) limits.ymin = (int)(MM_OSUNIT * atof(text + count));
  while ((count < max_val)&&(isdigit(text[count]))) count++;

  while  ((count < max_val)&&(!isdigit(text[count]))) count++;
  if (count < max_val) limits.xmax = (int)(MM_OSUNIT * atof(text + count));
  while ((count < max_val)&&(isdigit(text[count]))) count++;

  while  ((count < max_val)&&(!isdigit(text[count]))) count++;
  if (count < max_val) limits.ymax = (int)(MM_OSUNIT * atof(text + count));
  while ((count < max_val)&&(isdigit(text[count]))) count++;
  // help_text
  while  ((count < max_val)&&(!isalnum(text[count]))) count++;
  if (count < max_val) {
    	string_count = count;
  	while (!iscntrl(text[count])) count++;
  }
  if (count < max_val) {
        if ((count - string_count) > TOOLBAR_HELP) count = string_count + TOOLBAR_HELP;
  	help_text = new char[(count - string_count)+1];
  	strncpy(help_text, (text+string_count), (count - string_count));
  	help_text[count - string_count] = NULL;
  }
  else
        BadError(error_construct("Err_Obj"));
  (*counter) = count;
}

ToolBar_Window::ToolBar_Window(void)
{
  stage_count = number_of_stages = 0;
  ok_button = FALSE;
  stages = NULL;
}

/*----------------------------------------------------------------------ToolBar---*/
void
ToolBar_Window::SetStages(void)
{
  // open the instructions file and allocate an array
  // then copy the values
  _kernel_swi_regs regs;
  char *file_array, *stage_offset;
  FILE *fp;
  int i, array_offset =0;

  regs.r[0] = 17;	// get the size of the file
  regs.r[1] = (int)INSTRUCTIONS;
  Error(_kernel_swi(OS_File,&regs,&regs)) ;

  fp = fopen(INSTRUCTIONS, "r");
  if  ( fp == NULL){
        Error(error_construct("Err_File"));
        number_of_stages = 0;
        return;
  }

  file_array = new char[ regs.r[4] ];
  fread(file_array, regs.r[4], 1, fp);
  fclose(fp);

  number_of_stages = atoi(file_array);
  stages = new stage[number_of_stages];

  for (i = 0; i < number_of_stages; i++){
        stage_offset = strstr((&file_array[array_offset]), "STAGE");	// search for stage
 	if (stage_offset != NULL){
 	  while ((*stage_offset) != EOL) stage_offset++;			// look past 'stage' line
 	  array_offset = stage_offset - file_array;
 	  stages[i].set_stage(file_array, &array_offset, regs.r[4]);
  	TRACE("%s", stages[i].file_name);
  	TRACE("stage[%i] %i, %i, %i, %i", i, stages[i].limits.xmin, stages[i].limits.ymin,
  			    stages[i].limits.xmax, stages[i].limits.ymax);
        TRACE("%s", stages[i].help_text);
        }
  }
  delete file_array;
}

void
ToolBar_Window::Attach(ObjectId id)
{
  Window::Attach(id);	// attach this to the object
  help_message.Attach(mOID, 0x11);
  print_button.Attach(mOID, 0x10);
  skip_button.Attach(mOID, 0x12);
  reverse_button.Attach(mOID, 0x13);
  SetStages();
  if (stages == NULL)
  	BadError(error_construct("Err_Obj"));
  set_ok_button();
  SetHelpText(stages[stage_count].help_text);
}

void
ToolBar_Window::SetHelpText(char *help_text)
{
  if (Error(help_message.SetValue(0, help_text)))
  	  TRACE("ERROR: setting the value");
}

void
ToolBar_Window::DispatchEvent( ToolboxEvent *event, IdBlock *idb )
{
  Object *df;
  if (idb->parent_id == NULL) return;	// avoid the obvious error

  if (event->hdr.event_code == ActionButton_Selected){
    GetObjectFromId(idb->parent_id, &df);
    if (idb->self_component == 0x10)
       if (ok_button)
       	((drawfile*)df)->next_stage(+1);
       else
   	((drawfile*)df)->request_print();
    else
    if (idb->self_component == 0x12) // skip
    	((drawfile*)df)->next_stage(+1);
    else
    if (idb->self_component == 0x13) // back
        ((drawfile*)df)->next_stage(-1);
  }
}

void
ToolBar_Window::OnHasBeenHiddenEvent( WindowHasBeenHiddenEvent *has_been_hidden, IdBlock *idb )
{
  // if this object closes it kills the parent, this ensures that the stages are always there
  Object *df;
  has_been_hidden = has_been_hidden;

  GetObjectFromId(idb->parent_id, &df);
   ((drawfile*)df)->Hide(0);		// kill the parent
}

int
ToolBar_Window::next_stage(int amount)
{
  int end_value = FALSE;
  TRACE("change stage %i, %i", stage_count, number_of_stages);
   stage_count += amount;

   if (stage_count > (number_of_stages-1)){
        stage_count = 0;
        end_value = TRUE;
   }
   if (stage_count < 0){
        stage_count = number_of_stages-1;
        end_value = TRUE;
   }
   set_ok_button();
   SetHelpText(stages[stage_count].help_text);
   return end_value;
}

void
ToolBar_Window::set_ok_button(void)
{
  // this sets the selection button to OK instead of print if the area is zero
  unsigned int flags;

  if (stages[stage_count].zero_area() && !ok_button){
    	// set ok
    	print_button.SetText(0, "OK");
  	Error(skip_button.GetFlags(0,&flags));
  	flags = flags | Gadget_Faded;
  	Error(skip_button.SetFlags(0,flags));
  	Error(reverse_button.GetFlags(0,&flags));
  	flags = flags | Gadget_Faded;
  	Error(reverse_button.SetFlags(0,flags));
  	ok_button = TRUE;
  }
  else
  if (ok_button){
    	// set print
    	print_button.SetText(0, "Print");
  	Error(skip_button.GetFlags(0,&flags));
  	flags = flags & ~Gadget_Faded;
  	Error(skip_button.SetFlags(0,flags));
  	Error(reverse_button.GetFlags(0,&flags));
  	flags = flags & ~Gadget_Faded;
  	Error(reverse_button.SetFlags(0,flags));
  	ok_button = FALSE;
  }
}
