// 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 "main.h"
#include "tboxclass.h"
#include "menu.h"
#include "toolbox.h"

extern PalTask abc_task;

void
MainMenu::OnSelectionEvent( MenuSelectionEvent *selection, IdBlock *idb )
{
    Menu::OnSelectionEvent( selection, idb );
    if ( idb->self_component == 0 )
       abc_task.Finalise();
}

WaitMessage::WaitMessage(ObjectId w_obj, int a_code)
{
  waiting_object = w_obj;
  action_code = a_code;
  next = NULL;
}

void
PalTask::OnAutoCreatedEvent( ToolboxObjectAutoCreatedEvent *auto_created, IdBlock *idb )
{
    ToolboxTask::OnAutoCreatedEvent( auto_created, idb );

    if ( strcmp(auto_created->template_name, "IconMenu") == 0 )
    	mIconMenu.Attach( idb->self_id );

    if ( strcmp(auto_created->template_name, "PalChoose") == 0 )
    	pal_choose.Attach( idb->self_id );
}

void
PalTask::DispatchEvent(int event)
{
  void *ObjectInstance;
  IdBlock *idb;

  if (event  == Wimp_ERedrawWindow){
    idb = GetIdBlock();
      GetObjectFromId((GetIdBlock()->self_id), &ObjectInstance); 	// get the object that needs redrawing
      ((drawfile*)ObjectInstance)->redraw();
  }

  ToolboxTask::DispatchEvent( event );
}

/*----messages-----------------------------------------------------------------------------------------*/
void
PalTask::OnUserMessageEvent( WimpUserMessageEvent *user_message )
{
  TRACE("received user message %X", user_message->hdr.action_code);
  user_message_list.FindAndImplimentMessageFunction(user_message->hdr.action_code,
  						(WimpMessage*)user_message);
  ToolboxTask::OnUserMessageEvent(user_message);
}

void
PalTask::OnUserMessageRecordedEvent( WimpUserMessageRecordedEvent *user_message_recorded )
{
  TRACE("received user message, Recorded %X", user_message_recorded->hdr.action_code);

  recorded_message_list.FindAndImplimentMessageFunction(user_message_recorded->hdr.action_code,
  							(WimpMessage*)user_message_recorded);
  ToolboxTask::OnUserMessageRecordedEvent( user_message_recorded );
}

void
PalTask::OnUserMessageAcknowledgeEvent( WimpUserMessageAcknowledgeEvent *user_message_acknowledge )
{
  TRACE("received user message, Acknowledge %X", user_message_acknowledge->hdr.action_code);
  acknowledge_message_list.FindAndImplimentMessageFunction(user_message_acknowledge->hdr.action_code,
  							(WimpMessage*)user_message_acknowledge);
  ToolboxTask::OnUserMessageAcknowledgeEvent( user_message_acknowledge );
}

MessageList::MessageList(void)
{
    MessageObject = NULL;
}

MessageList::~MessageList(void)		// discard message waiting list
{
   WaitMessage *Temp;

   Temp = MessageObject;
   while (Temp != NULL){
     Temp = Temp->next;
     delete MessageObject;
     MessageObject = Temp;
   }
}

void
MessageList::RegisterWaitingForMessage(ObjectId w_obj, int a_code)
{
    WaitMessage *Temp;	// inserts a message in the front of the list

    Temp = MessageObject;	// the address of the first object
    MessageObject = new WaitMessage(w_obj, a_code);// new first object
    MessageObject->next = Temp;	// the new first object points to the old
}


void
MessageList::DeRegisterWaitingForMessage(ObjectId w_obj, int a_code)
{
      WaitMessage *Temp, *Temp_a;	// temp ->last object, temp_a -> this (in linked list)

      Temp = Temp_a = MessageObject;	// initialise both pointers

      while (Temp_a != NULL){
        if ((a_code == Temp_a->action_code)&&(w_obj == Temp_a->waiting_object)){// if this waitmessage
          	if (Temp_a == MessageObject){
          		MessageObject = Temp->next;
          		delete Temp;
          	}// first case
          	else{
               		Temp->next = Temp_a->next;
               		delete Temp_a;
          	}// delete this and correct next pointer.
        }// end if message
        if (Temp_a == MessageObject)// first case incriment
        	Temp_a = Temp_a->next;
        else{
          	Temp_a = Temp_a->next;
          	Temp = Temp->next;
        }
      }//while
}


void
MessageList::DeRegisterWaitingForMessage(ObjectId w_obj)
{
      WaitMessage *Temp, *Temp_a;	// temp ->last object, temp_a -> this (in linked list)

      Temp = Temp_a = MessageObject;	// initialise both pointers

      while (Temp_a != NULL){
        if (w_obj == Temp_a->waiting_object){// if this waitmessage
          if (Temp_a == MessageObject){
          	MessageObject = Temp->next;
          	delete Temp;
          }// first case
          else{
               Temp->next = Temp_a->next;
               delete Temp_a;
          }// delete this and correct next pointer.
        }// end if
        if (Temp_a == MessageObject)// first case incriment
        	Temp_a = Temp_a->next;
        else{
          Temp_a = Temp_a->next;
          Temp = Temp->next;
        }
      }//while
}

void
MessageList::FindAndImplimentMessageFunction(int action_code, WimpMessage *message)
{
    WaitMessage *Temp;
    void *WaitingForMessageObject;
    Temp = MessageObject;
    while (Temp != NULL){
    	if (Temp->action_code == action_code){
      		abc_task.GetObjectFromId(Temp->waiting_object, &WaitingForMessageObject);
      		((drawfile*)WaitingForMessageObject)->MessageHandler(message);
      				// we need to break on the first one as most
     		break;		//  will deregister their handler this has obvious repercussions
     	}
     	Temp = Temp->next;
    }//while
}
