/*  Core Wars.
 *  Copyright (C) 1999  Walter Hofmann
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as 
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef CMD_LINE
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <gtk/gtk.h>
#include <glib.h>

#include "main.h"
#include "main-gui.h"
#include "execute-cw.h"
#include "program.h"
#include "select.h"
#include "statistic.h"
#include "pstatistic.h"
#endif

#include "options.h"

#ifndef CMD_LINE
GtkWidget *options_window = NULL;
GtkWidget *corewars_item;
GtkWidget *redcode_item;
GtkWidget *language_menu;
GtkWidget *language_option_menu;
GtkWidget *size_entry;
GtkWidget *maxthreads_entry;
GtkWidget *maxcycles_entry;
GtkWidget *maxlength_entry;
GtkWidget *mindistance_entry;
GtkWidget *stopearly_button;
GtkWidget *allowselfmove_button;
GtkWidget *executedelay_entry;
GtkWidget *executeupdate_entry;
GtkWidget *statisticdelay_entry;
GtkWidget *scorealive_entry;
GtkWidget *scorecells_entry;
GtkWidget *scorekills_entry;
GtkWidget *tournament_add_button;
GtkWidget *tournament_rank_button;
GtkWidget *tournament_best_button;
GtkWidget *tournament_sum_button;
GtkWidget *editor_entry;
#endif

int LANGUAGE = LANGUAGE_STANDARD;

int SIZE = SIZE_STANDARD;
int DIMENSIONX;
int DIMENSIONY;
int MAX_THREADS = MAX_THREADS_STANDARD;
int MAX_CYCLES = MAX_CYCLES_STANDARD;
int MAX_LENGTH = MAX_LENGTH_STANDARD;
int MIN_DISTANCE = MIN_DISTANCE_STANDARD;
int STOP_EARLY = STOP_EARLY_STANDARD;

int ALLOW_SELF_MOVE = ALLOW_SELF_MOVE_STANDARD;

int EXECUTE_DELAY = EXECUTE_DELAY_STANDARD;
int EXECUTE_UPDATE = EXECUTE_UPDATE_STANDARD;
int STATISTIC_DELAY = STATISTIC_DELAY_STANDARD;

int SCORE_ALIVE = SCORE_ALIVE_STANDARD;
int SCORE_CELLS = SCORE_CELLS_STANDARD;
int SCORE_KILLS = SCORE_KILLS_STANDARD;

int SCORE_RANK = 0;
int SCORE_BEST = 0;

char EDIT_COMMAND[1024] = EDIT_COMMAND_STANDARD;

#ifndef CMD_LINE
void options_window_apply (GtkWidget *w, gpointer data)
{
  int newlanguage;
  int newsize;
  int newmaxthreads;
  int newmaxcycles;
  int newmaxlength;
  int newmindistance;
  int language_changed;
  int variables_changed;

  if (!running)
    {
      if (gtk_menu_get_active (GTK_MENU (language_menu))==corewars_item)
	  newlanguage = LANGUAGE_CW;
      else if (gtk_menu_get_active (GTK_MENU (language_menu))==redcode_item)
	  newlanguage = LANGUAGE_RC;
      newsize = MIN (SIZE_MAX, 
		     MAX (SIZE_MIN, 
			  atoi (gtk_entry_get_text (GTK_ENTRY (size_entry)))));
      newmaxthreads = MAX (1, atoi (gtk_entry_get_text (GTK_ENTRY (maxthreads_entry))));
      newmaxcycles = MAX (1, atoi (gtk_entry_get_text (GTK_ENTRY (maxcycles_entry))));
      newmaxlength = MAX (1, atoi (gtk_entry_get_text (GTK_ENTRY (maxlength_entry))));
      newmindistance = MAX (1, atoi (gtk_entry_get_text (GTK_ENTRY (mindistance_entry))));
      STOP_EARLY = GTK_TOGGLE_BUTTON (stopearly_button)->active;
      ALLOW_SELF_MOVE = GTK_TOGGLE_BUTTON (allowselfmove_button)->active;
      language_changed = (newlanguage!=LANGUAGE);
      variables_changed = (newsize!=SIZE || newmaxthreads!=MAX_THREADS  ||
	  newmaxcycles!=MAX_CYCLES || newmaxlength!=MAX_LENGTH || newmindistance!=MIN_DISTANCE);
      if (language_changed || variables_changed)
	execute_cleanup ();
      LANGUAGE = newlanguage;
      if (newsize!=SIZE)      
	{
	  SIZE = newsize;
	  DIMENSIONX = (int) sqrt (SIZE);
	  DIMENSIONY = (SIZE+DIMENSIONX-1)/DIMENSIONX;
	  gtk_widget_hide (main_window);
	  gtk_drawing_area_size (GTK_DRAWING_AREA (main_drawing_area), 
				 6*DIMENSIONX+1, 6*DIMENSIONY+1);
	  gtk_widget_show (main_window);
	}
      MAX_THREADS = newmaxthreads;
      MAX_CYCLES = newmaxcycles;
      MAX_LENGTH = newmaxlength;
      MIN_DISTANCE = newmindistance;
      if (variables_changed)
	program_update ();
      if (language_changed || variables_changed)
	{
	  select_update_list ();
	  pstatistic_update ();
	  menu_start_update ();
	}
    }
  EXECUTE_DELAY = MAX (EXECUTE_DELAY_MIN, 
		       atoi (gtk_entry_get_text (GTK_ENTRY (executedelay_entry))));
  EXECUTE_UPDATE = MAX (1, atoi (gtk_entry_get_text (GTK_ENTRY (executeupdate_entry))));
  STATISTIC_DELAY = MAX (STATISTIC_DELAY_MIN, 
			 atoi (gtk_entry_get_text (GTK_ENTRY (statisticdelay_entry))));
  if (running)
    {
      gtk_timeout_remove (execute_timeout);
      gtk_timeout_remove (statistic_timeout);
      execute_timeout = gtk_timeout_add (EXECUTE_DELAY, execute_step_handler, NULL);
      statistic_timeout = gtk_timeout_add (STATISTIC_DELAY, statistic_handler, NULL);
    }
  SCORE_ALIVE = atoi (gtk_entry_get_text (GTK_ENTRY (scorealive_entry)));
  SCORE_CELLS = atoi (gtk_entry_get_text (GTK_ENTRY (scorecells_entry)));
  SCORE_KILLS = atoi (gtk_entry_get_text (GTK_ENTRY (scorekills_entry)));
  statistic_update (FALSE);
  SCORE_RANK = GTK_TOGGLE_BUTTON (tournament_rank_button)->active;
  SCORE_BEST = GTK_TOGGLE_BUTTON (tournament_best_button)->active;
  strncpy (EDIT_COMMAND, gtk_entry_get_text (GTK_ENTRY (editor_entry)), 1024);
  EDIT_COMMAND[1023] = '\0';
}

void options_window_ok (GtkWidget *w, gpointer data)
{
  options_window_apply (w, data);
  gtk_widget_destroy (options_window);
}

GtkWidget *new_entry (GtkWidget *table, char *labeltext, int row, int length, int value)
{
  GtkWidget *label;
  GtkWidget *entry;

  label = gtk_label_new (labeltext);
  gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, row, row+1);
  gtk_widget_show (label);
  entry = gtk_entry_new_with_max_length (length);
  gtk_entry_set_text (GTK_ENTRY (entry), itos (value));
  gtk_widget_set (entry, "width", OPTIONS_ENTRY_WIDTH, NULL);
  gtk_table_attach (GTK_TABLE (table), entry, 1, 2, row, row+1, 
		    GTK_SHRINK, 0, 1, 1);
  gtk_widget_show (entry);
  return entry;
}

/* Options */ 
void view_options (GtkWidget *w, gpointer data)
{
  GtkWidget *okbutton, *applybutton, *cancelbutton;
  GtkWidget *notebook;
  GtkWidget *frame, *label;
  GtkWidget *table;
  GtkWidget *vbox;
  GtkWidget *sep;

  if (!options_window)
    {
      options_window = gtk_dialog_new ();
      gtk_signal_connect (GTK_OBJECT (options_window), "destroy", 
			  GTK_SIGNAL_FUNC (gtk_widget_destroyed), &options_window);
      gtk_window_set_title (GTK_WINDOW (options_window), "Options");
      notebook = gtk_notebook_new ();

      frame = gtk_frame_new ("General settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      table = gtk_table_new (2, 7, FALSE);
      label = gtk_label_new ("Language:");
      gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
      gtk_widget_show (label);
      language_menu = gtk_menu_new();
      corewars_item = gtk_menu_item_new_with_label ("Corewars");
      gtk_menu_append (GTK_MENU (language_menu), corewars_item);
      gtk_widget_show (corewars_item);
      redcode_item = gtk_menu_item_new_with_label ("Redcode");
      gtk_menu_append (GTK_MENU (language_menu), redcode_item);
      gtk_widget_show (redcode_item);
      gtk_menu_set_active (GTK_MENU (language_menu), LANGUAGE-1); 
      gtk_widget_show (language_menu);
      language_option_menu = gtk_option_menu_new ();
      gtk_option_menu_set_menu (GTK_OPTION_MENU (language_option_menu), language_menu);
      gtk_table_attach (GTK_TABLE (table), language_option_menu, 1, 2, 0, 1, 
			GTK_SHRINK, 0, 1, 1);
      gtk_widget_show (language_option_menu);
      size_entry = new_entry (table, "Memory size:", 1, 7, SIZE);
      maxthreads_entry = new_entry (table, "Maximum threads per process:", 2, 5, MAX_THREADS);
      maxcycles_entry = new_entry (table, "Maximum number of cycles:", 3, 9, MAX_CYCLES);
      maxlength_entry = new_entry (table, "Maximum length of programs:", 4, 5, MAX_LENGTH);
      mindistance_entry = new_entry (table, "Minimum distance between processes:", 5, 5, MIN_DISTANCE);
      stopearly_button = gtk_check_button_new_with_label ("Stop when only one process left");
      gtk_table_attach (GTK_TABLE (table), stopearly_button, 0, 1, 6, 7, 
			GTK_SHRINK, 0, 1, 1);
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stopearly_button), STOP_EARLY);
      gtk_widget_show (stopearly_button);
      gtk_container_add (GTK_CONTAINER (frame), table);
      gtk_widget_show (table);
      label = gtk_label_new ("General");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      frame = gtk_frame_new ("Corewars settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      table = gtk_table_new (2, 1, FALSE);
      allowselfmove_button = gtk_check_button_new_with_label ("Allow self move");
      gtk_table_attach (GTK_TABLE (table), allowselfmove_button, 0, 2, 0, 1, 
			GTK_SHRINK, 0, 1, 1);
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (allowselfmove_button), ALLOW_SELF_MOVE);
      gtk_widget_show (allowselfmove_button);
      gtk_container_add (GTK_CONTAINER (frame), table);
      gtk_widget_show (table);
      label = gtk_label_new ("Corewars");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      frame = gtk_frame_new ("Display settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      table = gtk_table_new (3, 2, FALSE);
      executedelay_entry = new_entry (table, "Delay between execution blocks (ms):", 0, 5, EXECUTE_DELAY);
      executeupdate_entry = new_entry (table, "Number of steps in each execution block:", 1, 5, EXECUTE_UPDATE);
      statisticdelay_entry = new_entry (table, "Statistic update delay (ms):", 2, 5, STATISTIC_DELAY);
      gtk_container_add (GTK_CONTAINER (frame), table);
      gtk_widget_show (table);
      label = gtk_label_new ("Display");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      frame = gtk_frame_new ("Game scoring settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      table = gtk_table_new (3, 2, FALSE);
      scorealive_entry = new_entry (table, "Alive points:", 0, 5, SCORE_ALIVE);
      scorecells_entry = new_entry (table, "Cell points:", 1, 5, SCORE_CELLS);
      scorekills_entry = new_entry (table, "Kill points:", 2, 5, SCORE_KILLS);
      gtk_container_add (GTK_CONTAINER (frame), table);
      gtk_widget_show (table);
      label = gtk_label_new ("Game score");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      frame = gtk_frame_new ("Program score settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      vbox = gtk_vbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER (frame), vbox);
      gtk_widget_show (vbox);
      tournament_add_button = gtk_radio_button_new_with_label (NULL, "Use game score");
      gtk_box_pack_start (GTK_BOX (vbox), tournament_add_button, FALSE, FALSE, 0);
      gtk_widget_show (tournament_add_button);
      tournament_rank_button = gtk_radio_button_new_with_label_from_widget 
	(GTK_RADIO_BUTTON (tournament_add_button), "Use rank in game statistic");
      gtk_box_pack_start (GTK_BOX (vbox), tournament_rank_button, FALSE, FALSE, 0);
      gtk_widget_show (tournament_rank_button);
      if (SCORE_RANK)
	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tournament_rank_button), TRUE);
      else
	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tournament_add_button), TRUE);
      sep = gtk_hseparator_new ();
      gtk_box_pack_start (GTK_BOX (vbox), sep, FALSE, FALSE, 0);
      gtk_widget_show (sep);
      tournament_best_button = gtk_radio_button_new_with_label (NULL, "Use score of best copy");
      gtk_box_pack_start (GTK_BOX (vbox), tournament_best_button, FALSE, FALSE, 0);
      gtk_widget_show (tournament_best_button);
      tournament_sum_button = gtk_radio_button_new_with_label_from_widget 
	(GTK_RADIO_BUTTON (tournament_best_button), "Sum scores of all copies");
      gtk_box_pack_start (GTK_BOX (vbox), tournament_sum_button, FALSE, FALSE, 0);
      gtk_widget_show (tournament_sum_button);
      if (SCORE_BEST)
	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tournament_best_button), TRUE);
      else
	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tournament_sum_button), TRUE);
      label = gtk_label_new ("Program Score");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      frame = gtk_frame_new ("Editor settings");
      gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
      gtk_widget_show (frame);
      table = gtk_table_new (1, 2, FALSE);
      label = gtk_label_new ("Editor:");
      gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
      gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
      gtk_widget_show (label);
      editor_entry = gtk_entry_new_with_max_length (1023);
      gtk_entry_set_text (GTK_ENTRY (editor_entry), EDIT_COMMAND);
      gtk_widget_set (editor_entry, "width", OPTIONS_ENTRY_WIDTH, NULL);
      gtk_table_attach (GTK_TABLE (table), editor_entry, 1, 2, 0, 1, 
			GTK_SHRINK, 0, 1, 1);
      gtk_widget_show (editor_entry);
      gtk_container_add (GTK_CONTAINER (frame), table);
      gtk_widget_show (table);
      label = gtk_label_new ("Editor");
      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);

      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (options_window)->vbox),
			  notebook, TRUE, TRUE, 0);
      gtk_widget_show (notebook);
      okbutton = gtk_button_new_with_label( "Ok" );
      gtk_signal_connect (GTK_OBJECT (okbutton), "clicked", 
			  GTK_SIGNAL_FUNC (options_window_ok), NULL);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (options_window)->action_area),
			  okbutton, TRUE, TRUE, 0);
      gtk_widget_show (okbutton);
      applybutton = gtk_button_new_with_label( "Apply" );
      gtk_signal_connect (GTK_OBJECT (applybutton), "clicked", 
			  GTK_SIGNAL_FUNC (options_window_apply), NULL);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (options_window)->action_area),
			  applybutton, TRUE, TRUE, 0);
      gtk_widget_show (applybutton);
      cancelbutton = gtk_button_new_with_label( "Cancel" );
      gtk_signal_connect_object (GTK_OBJECT (cancelbutton), "clicked", 
				 GTK_SIGNAL_FUNC (gtk_widget_destroy),
				 GTK_OBJECT (options_window)); 
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (options_window)->action_area),
			  cancelbutton, TRUE, TRUE, 0);
      gtk_widget_show (cancelbutton);
      gtk_widget_show (options_window);
      options_update ();
    }
  else
    gdk_window_raise (options_window->window);
}

void options_update ()
{
  if (options_window)
    if (running)
      {
	gtk_entry_set_text (GTK_ENTRY (size_entry), itos (SIZE));
	gtk_entry_set_text (GTK_ENTRY (maxthreads_entry), itos (MAX_THREADS));
	gtk_entry_set_text (GTK_ENTRY (maxcycles_entry), itos (MAX_CYCLES));
	gtk_entry_set_text (GTK_ENTRY (maxlength_entry), itos (MAX_LENGTH));
	gtk_entry_set_text (GTK_ENTRY (mindistance_entry), itos (MIN_DISTANCE));
	gtk_option_menu_set_history (GTK_OPTION_MENU (language_option_menu), LANGUAGE-1); 
	gtk_widget_set (GTK_WIDGET (language_option_menu), "sensitive", FALSE, NULL);
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (allowselfmove_button), ALLOW_SELF_MOVE);
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (stopearly_button), STOP_EARLY);
	gtk_widget_set (GTK_WIDGET (size_entry), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (maxthreads_entry), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (maxcycles_entry), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (maxlength_entry), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (mindistance_entry), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (stopearly_button), "sensitive", FALSE, NULL);
	gtk_widget_set (GTK_WIDGET (allowselfmove_button), "sensitive", FALSE, NULL);
      }
    else
      {
	gtk_widget_set (GTK_WIDGET (language_option_menu), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (size_entry), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (maxthreads_entry), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (maxcycles_entry), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (maxlength_entry), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (mindistance_entry), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (stopearly_button), "sensitive", TRUE, NULL);
	gtk_widget_set (GTK_WIDGET (allowselfmove_button), "sensitive", TRUE, NULL);
      }
}
#endif
