/*  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.
 */

#include <gtk/gtk.h>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "main.h"
#include "main-gui.h"
#include "program.h"
#include "select.h"
#include "execute.h"
#include "tournament.h"
#include "pstatistic.h"

GtkWidget *select_window = NULL;
GtkWidget *select_scrolled_window;
GtkWidget *select_window_table;
GtkWidget *select_window_okbutton, *select_window_applybutton;
GtkWidget *select_window_refreshbutton, *select_window_cancelbutton;

void select_window_apply (GtkWidget *w, gpointer data)
{
  struct program *p;

  p = program_list_root;
  while (p)
    {
      p->load_count = MAX (0, 
			   MIN (MAX_LOAD_COUNT, 
				atoi (gtk_entry_get_text (GTK_ENTRY (p->entry)))));
      p = p->next;
    }
  menu_start_update ();
  pstatistic_update ();
}

void select_window_refresh (GtkWidget *w, gpointer data)
{
  recheck_program_list ();
  menu_start_update ();
  pstatistic_update ();
}

void select_window_ok (GtkWidget *w, gpointer data)
{
  select_window_apply (w, data);
  gtk_widget_destroy (select_window);
}

int program_title_compare (const void *a, const void *b)
{
  if (!(*(struct program **)a)->title)
    return -1;
  if (!(*(struct program **)b)->title)
    return +1;
  return strcmp((*(struct program **)a)->title, (*(struct program **)b)->title);
}

/* Load Program */
void file_selectprograms (GtkWidget *w, gpointer data)
{
  if (!select_window)
    {
      if (!running)
	recheck_program_list ();

      select_window = gtk_dialog_new ();
      gtk_signal_connect (GTK_OBJECT (select_window), "destroy", 
			  GTK_SIGNAL_FUNC (gtk_widget_destroyed), &select_window);
      gtk_window_set_title (GTK_WINDOW (select_window), "Program selection");
      select_scrolled_window = gtk_scrolled_window_new (NULL, NULL );
      gtk_widget_set_usize (GTK_WIDGET (select_scrolled_window), SELECT_WINDOW_WIDTH, SELECT_WINDOW_HEIGHT);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (select_scrolled_window), 
				      GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); 
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (select_window)->vbox),
			  select_scrolled_window, TRUE, TRUE, 0);

      select_window_table = NULL;
      select_update_list ();

      gtk_widget_show (select_scrolled_window);
      select_window_okbutton = gtk_button_new_with_label( "Ok" );
      gtk_signal_connect (GTK_OBJECT (select_window_okbutton), "clicked", 
			  GTK_SIGNAL_FUNC (select_window_ok), NULL);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (select_window)->action_area),
			  select_window_okbutton, TRUE, TRUE, 0);
      gtk_widget_show (select_window_okbutton);
      select_window_applybutton = gtk_button_new_with_label( "Apply" );
      gtk_signal_connect (GTK_OBJECT (select_window_applybutton), "clicked", 
			  GTK_SIGNAL_FUNC (select_window_apply), NULL);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (select_window)->action_area),
			  select_window_applybutton, TRUE, TRUE, 0);
      gtk_widget_show (select_window_applybutton);
      select_window_refreshbutton = gtk_button_new_with_label( "Refresh" );
      gtk_signal_connect (GTK_OBJECT (select_window_refreshbutton), "clicked", 
			  GTK_SIGNAL_FUNC (select_window_refresh), NULL);
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (select_window)->action_area),
			  select_window_refreshbutton, TRUE, TRUE, 0);
      gtk_widget_show (select_window_refreshbutton);
      select_window_cancelbutton = gtk_button_new_with_label( "Cancel" );
      gtk_signal_connect_object (GTK_OBJECT (select_window_cancelbutton), "clicked", 
				 GTK_SIGNAL_FUNC (gtk_widget_destroy),
				 GTK_OBJECT (select_window)); 
      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (select_window)->action_area),
			  select_window_cancelbutton, TRUE, TRUE, 0);
      gtk_widget_show (select_window_cancelbutton);
      gtk_widget_show (select_window);
      select_update ();
    }
  else
    gdk_window_raise (select_window->window);
}

void select_update ()
{
  if (select_window)
    {
      gtk_widget_set (select_window_okbutton, "sensitive", !running, NULL);
      gtk_widget_set (select_window_applybutton, "sensitive", !running, NULL);
      gtk_widget_set (select_window_refreshbutton, "sensitive", !running, NULL);
    }
}

static void select_focus_in_handler (GtkWidget *w, void *data, int index)
{
  int h;

  h = GTK_TABLE (select_window_table)->rows[0].requisition;
  gtk_adjustment_clamp_page (GTK_RANGE (GTK_SCROLLED_WINDOW (select_scrolled_window)->vscrollbar)->adjustment,
			     h*index, h*(index+1));
}

static void select_edit_clicked (GtkWidget *w, struct program *p)
{
  char s[1024];

  snprintf (s, 1024, "%s \"%s\" &", EDIT_COMMAND, p->filename);
  s[1023] = '\0';
  system (s);
}

char *language_names[] = { " [Corewars] ", " [Redcode] " };

void select_update_list ()
{
  struct program *p;
  int n,i;
  struct program **table;
  GtkWidget *label;
  GtkWidget *button;
  char labeltext[1024];

  if (select_window)
    {
      p = program_list_root;
      n = 0;
      while (p)
	{
	  n++;
	  p = p->next;
	}
      if (n)
	{
	  table = (struct program **) malloc(sizeof(struct program *)*n);
	  p = program_list_root;
	  i = 0;
	  while (p)
	    {
	      table[i++] = p;
	      p = p->next;
	    }
	  qsort (table, n, sizeof (struct program *), &program_title_compare);
	  program_list_root = table[0];
	  for (i=0; i<n; i++)
	    {
	      if (i==0)
		table[i]->prev = NULL;
	      else
		table[i]->prev = table[i-1];
	      if (i==n-1)
		table[i]->next = NULL;
	      else
		table[i]->next = table[i+1];
	    }
	  free(table);
	}
      if (select_window_table)
	gtk_container_remove (GTK_CONTAINER (GTK_BIN (select_scrolled_window)->child), select_window_table);
      select_window_table = gtk_table_new (n, 4, FALSE);
      gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (select_scrolled_window), 
					     select_window_table);
      n = 0;
      p = program_list_root;
      while (p)
	{
	  button = gtk_button_new_with_label( " Edit " );
	  gtk_signal_connect (GTK_OBJECT (button), "clicked", 
			      GTK_SIGNAL_FUNC (select_edit_clicked), (gpointer) p);
	  gtk_table_attach (GTK_TABLE (select_window_table), button,
			    0, 1, n, n+1, 0, 0, 1, 1);
	  gtk_signal_connect (GTK_OBJECT (button), "focus-in-event", 
			      GTK_SIGNAL_FUNC (select_focus_in_handler),
			      (gpointer) n); 
	  gtk_widget_show (button);
	  p->entry = gtk_entry_new_with_max_length (LOAD_COUNT_LINE_LENGTH);
	  gtk_widget_set (GTK_WIDGET (p->entry), "width", LOAD_COUNT_WIDTH, NULL);
	  if (tournament_running)
	    gtk_entry_set_text (GTK_ENTRY (p->entry), itos (p->tournament_count));
	  else
	    gtk_entry_set_text (GTK_ENTRY (p->entry), itos (p->load_count));
	  gtk_table_attach (GTK_TABLE (select_window_table), p->entry,
			    1, 2, n, n+1, 0, 0, 1, 1);
	  if (p->error || p->language!=LANGUAGE)
	    gtk_widget_set (GTK_WIDGET (p->entry), "sensitive", FALSE, NULL);
	  else
	    gtk_tooltips_set_tip (gtk_tooltips_new (), p->entry, 
				  "Enter number of instances to load", NULL);
	  gtk_signal_connect (GTK_OBJECT (p->entry), "focus-in-event", 
			      GTK_SIGNAL_FUNC (select_focus_in_handler),
			      (gpointer) n); 
	  gtk_widget_show (p->entry);
	  label = gtk_label_new(language_names[p->language-1]); 
	  gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
	  gtk_table_attach (GTK_TABLE (select_window_table), label,
			    2, 3, n, n+1, GTK_FILL, 0, 0, 0);
	  gtk_widget_show (label);
	  if (p->error)
	    label = gtk_label_new(p->error); 
	  else
	    {
	      snprintf(labeltext, 1024, "%s (%s)", p->title, p->author);
	      labeltext[1023] = '\0';
	      label = gtk_label_new(labeltext); 
	    }
	  gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
	  gtk_table_attach (GTK_TABLE (select_window_table), label,
			    3, 4, n, n+1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
	  gtk_widget_show (label);
	  n++;
	  p = p->next;
	}
      gtk_widget_show (select_window_table);
    }
}
