/* actions.cc 1.14 95/12/28 23:24:14 */


// xspacewarp by Greg Walker (gow@math.orst.edu)

// This is free software. Non-profit redistribution and/or modification
// is allowed and welcome.


// most of the Intrisics actions used in this program are in this file
// but some more actions related to data entry are in echoarea.cc


#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <stdlib.h>
#include <iostream.h>
#include "common.hh"
#include "params.hh"
#include "globals.hh"
#include "c_endever.hh"
#include "messages.hh"

extern void draw_intro(void);
extern void draw_mission(void);
extern void draw_scanner(void);
extern void draw_summary(void);
extern void draw_sector(void);
extern void draw_orientation(int);
extern void erase_universe(void);
extern void echo(const char *, int);
extern void clear_echo(void);
extern void move_to(XtPointer client_data, XtIntervalId *id);
extern void energize_to(XtPointer client_data, XtIntervalId *id);
extern void jovian_to(XtPointer client_data, XtIntervalId *id);
extern void reseed_to(XtPointer client_data, XtIntervalId *id);

static void startgame(void);


// to handle expose events

void expose(Widget w, XEvent *event, String *str, Cardinal *len)
{
  XCopyArea(DISPLAY, pixmap, XtWindow(w), def_GC,
	    event->xexpose.x, event->xexpose.y,
	    event->xexpose.width, event->xexpose.height,
	    event->xexpose.x, event->xexpose.y);
}


// handles keyboard input when "Mission" statement being displayed.
// Xdefaults need to pass one of the 2 args: "start", "orient" to
// mission().

void mission(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.visual != MISSION) // wrong state
     return;
  if (*len = 0)			// missing arguments
  {
    cerr << "xspacewarp: mission: unknown argument in X defaults." << endl;
    exit(1);
  }

  switch (str[0][0])
  {
  case 's':			// start game
    draw_sector();
    gamestate.visual = SECTOR;
    gamestate.input = ACTION;
    startgame();
    break;
  case 'o':			// start orientation
    draw_orientation(1);
    gamestate.visual = ORIENTATION;
    break;
  default:
      cerr << "xspacewarp: mission: unknown argument in X defaults." << endl;
      exit(1);
  }    
}


// manages keyboard input for the xspacewarp orientation pages.
// Xdefaults need to pass one of the 3 args: "next", "prev", "quit"
// to orientation()

void orientation(Widget w, XEvent *event, String *str, Cardinal *len)
{
  static int curpage = 1;	// current page number being read

  if (gamestate.visual != ORIENTATION) // wrong state
     return;
  if (*len = 0)			// missing arguments
  {
    cerr << "xspacewarp: orientation: unknown argument in X defaults." << endl;
    exit(1);
  }

  switch (str[0][0])
  {
  case 'n':			// view next page
    draw_orientation(++curpage);
    break;
  case 'p':			// view previous page
    draw_orientation(--curpage);
    break;
  case 'q':			// return to mission display
    curpage = 1;
    draw_mission();
    gamestate.visual = MISSION;
    break;
  default:
    cerr << "xspacewarp: orientation: unknown argument in X defaults." << endl;
    exit(1);
  }
}
    


// the "move" action requires that the resource have one of the 
// arguments "up", "down", "left", or "right". For example:
// <Key>i: move(up)

void move(Widget w, XEvent *event, String *str, Cardinal *len)
{

  if ((gamestate.input != ACTION) || (gamestate.visual != SECTOR))
     return;			// wrong state
  if (*len == 0)		// no arguments
  {
    cerr << "xspacewarp: move: unknown argument in X defaults." << endl;
    exit(1);
  }
  if (endever.nomove())		// wait for time-delay
     return;

  switch (str[0][0])
  {
  case 'u':
    endever.move(UP);
    break;
  case 'd':
    endever.move(DOWN);
    break;
  case 'l':
    endever.move(LEFT);
    break;
  case 'r':
    endever.move(RIGHT);
    break;
  default:
    cerr << "xspacewarp: move: unknown argument in X defaults." << endl;
    exit(1);
  }

  (void) XtAppAddTimeOut(app_context, MOVEINT,
			 (XtTimerCallbackProc) move_to, NULL);
  endever.setnomove(true);
}


// for changing visual state to the sector display.

void sector(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != ACTION)
     return;			// wrong state

  // erase pixmap, draw sector display on it and copy to visible window

  clear_echo();			// reset cursor position
  draw_sector();
  gamestate.visual = SECTOR;
}


// for changing visual state to the scanner display

void scanner(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != ACTION)
     return;			// wrong state

  clear_echo();			// reset cursor position
  draw_scanner();
  gamestate.visual = SCANNER;
}


// for changing visual state to the summary display

void summary(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != ACTION)
     return;			// wrong state

  clear_echo();			// reset cursor position
  draw_summary();
  gamestate.visual = SUMMARY;
}


// warp speed leap to a new sector

void leap(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != ACTION)
     return;			// wrong state
  gamestate.input = NEWSECTOR;
  clear_echo();
  echo(warpdrive_prompt_str, XtNumber(warpdrive_prompt_str)-1);
}


// action for changing shield levels

void shields(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != ACTION)
     return;			// wrong state
  gamestate.input = SHIELDLEVEL;
  clear_echo();
  echo(shields_prompt_str, XtNumber(shields_prompt_str)-1);
}


// action for starting a faser shot

void fasers(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if ((gamestate.input != ACTION) || (gamestate.visual != SECTOR))
     return;			// wrong state
  gamestate.input = FASERANGLE;
  clear_echo();
  echo(fasers_prompt_str, XtNumber(fasers_prompt_str)-1);
}


// action for starting a torpedo shot

void torpedoes(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if ((gamestate.input != ACTION) || (gamestate.visual != SECTOR))
     return;			// wrong state
  gamestate.input = TORPANGLE;
  clear_echo();
  echo(torpedo_prompt_str, XtNumber(torpedo_prompt_str)-1);
}


// action for initiating endever self-destruct.

void selfdestruct(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if ((gamestate.input != ACTION) || (gamestate.visual != SECTOR))
     return;			// wrong state
  gamestate.input = CODE;
  clear_echo();
  echo(selfdestruct_prompt_str, XtNumber(selfdestruct_prompt_str)-1);
}


// manage keyboard input when game over and being asked to restart game.
// In Xdefaults, must pass one of the 2 args: "yes" or "no" to replay().

void replay(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input != REPLAY) // wrong mode
     return;
  if (*len == 0)		// no arguments
  {
    cerr << "xspacewarp: replay: unknown argument in X defaults." << endl;
    exit(1);
  }

  switch (str[0][0])
  {
  case 'y':			// restart game
    erase_universe();
    clear_echo();
    draw_intro();
    gamestate.visual = INTRO;
    gamestate.input = SKILL;
    break;
  case 'n':			// quit xspacewarp
    cout << "Live long and prosper!" << endl;
    exit(0);
  default:
    cerr << "xspacewarp: replay: unknown argument in X defaults." << endl;
    exit(1);
  }
}


void pause(Widget w, XEvent *event, String *str, Cardinal *len)
{
  if (gamestate.input == ACTION)    // suspend game
  {
    clear_echo();
    echo(paused_str, XtNumber(paused_str) - 1);
    gamestate.input = PAUSE;
  }
  else if (gamestate.input == PAUSE)		 // resume game
  {
    clear_echo();
    gamestate.input = ACTION;
  }
}


// not an action but invoked by one.
// Initialize Jovian AI data and start AppTimeOuts so jovians
// begin attacking.

static void startgame(void)
{
  Jovian::init_ai();

  (void) XtAppAddTimeOut(app_context, JOVINT,
			 (XtTimerCallbackProc) jovian_to, NULL);
  (void) XtAppAddTimeOut(app_context, ERGINT,
			 (XtTimerCallbackProc) energize_to, NULL);
  (void) XtAppAddTimeOut(app_context, SEEDINT,
			 (XtTimerCallbackProc) reseed_to, NULL);
}

// end
