//
//  @(#)NGDStartOptions.java	4/2002
//
//  Copyright 2002 Zachary DelProposto. All rights reserved.
//  Use is subject to license terms.
//
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  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., 675 Mass Ave, Cambridge, MA 02139, USA.
//  Or from http://www.gnu.org/
//
package dip.gui.dialog.newgame;

import dip.world.*;
import dip.world.variant.data.Variant;
import dip.gui.swing.*;

import dip.misc.Utils;

import cz.autel.dmi.HIGConstraints;
import cz.autel.dmi.HIGLayout;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.JSeparator;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


/**
*
*	Defines the game starting options for the New Game dialog.
*	<p>
*	This allows the user to alter any game parameters before the 
*	game starts.
*	<p>
*	Reset button allows reversion to defaults.
*/
public class NGDStartOptions extends JPanel implements NewGameDialog.NGDTabPane
{
	// constants
	private static final int BORDER = 5;
	private static final String TAB_NAME 				= "NGDoptions.tab.name";
	private static final String BUTTON_RESET 			= "NGDoptions.button_reset";
	private static final String LABEL_TIME				= "NGDoptions.label_time";
	private static final String LABEL_VC				= "NGDoptions.label_vc";
	private static final String LABEL_VC_SC_REQ			= "NGDoptions.label_vc_sc_req";
	private static final String LABEL_VC_SC_NOCHANGE	= "NGDoptions.label_vc_sc_nochange";
	private static final String LABEL_VC_DURATION		= "NGDoptions.label_vc_duration";
	private static final String INTRO_TEXT_LOCATION		= "NGDoptions.location_intro_text";
	
	// instance variables
	private Variant current = null;	// current variant
	private Variant original = null;
	
	// GUI controls
	private JComboBox 	phaseBox;
	private BCSpinner	year;
	private JSpinner	vcSC;
	private JSpinner	vcSCChange;
	private JSpinner	vcDuration;
	private JButton		reset;
	private JEditorPane	introText;
	
	
	/** Create the StartOptions panel for the New Game dialog */
	public NGDStartOptions()
	{
		// create GUI controls
		phaseBox = new JComboBox();
		phaseBox.setEditable(false);
		
		year = new BCSpinner(1, 1, 9999);
		vcSC = makeCustomSpinner(true);
		vcSCChange = makeCustomSpinner(true);
		vcDuration = makeCustomSpinner(true);
		
		reset = new JButton( Utils.getLocalString(BUTTON_RESET) );
		reset.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if(original != null)
				{
					resetData();
				}
			}
		});
		
		
		introText = Utils.createTextLabel(true);
		introText.setText( Utils.getText(Utils.getLocalString(INTRO_TEXT_LOCATION)) );
		introText.setMargin(new Insets(10,0,10,0));
		
		makeLayout();
	}// NGDStartOptions()
	
	
	
	/** Gets the (possibly) modified Variant */
	public synchronized Variant getVariant()
	{
		// set game time
		StringBuffer sb = new StringBuffer();
		sb.append( phaseBox.getSelectedItem() );
		sb.append(' ');
		sb.append( year.getValue() );
		current.setStartingPhase( Phase.parse(sb.toString()) );
		
		// set victory conditions
		current.setNumSCForVictory( getSpinnerValue(vcSC) );
		current.setMaxYearsNoSCChange( getSpinnerValue(vcSCChange) );
		current.setMaxGameTimeYears( getSpinnerValue(vcDuration) );
		
		return current;
	}// getVariant()
	
	
	/** Enables & Disables controls on this panel */
	public void setEnabled(boolean value)
	{
	 	phaseBox.setEnabled(value);
		year.setEnabled(value);
		vcSC.setEnabled(value);
		vcSCChange.setEnabled(value);
		vcDuration.setEnabled(value);
		reset.setEnabled(value);
		introText.setEnabled(value);
		super.setEnabled(value);
	}// setEnabled()
	
	
	/** Set data from originally passed reference */
	private void resetData()
	{
		Phase phase = original.getStartingPhase();
		
		// set combo box
		phaseBox.removeAllItems();
		String[] combos = Phase.getAllSeasonPhaseCombos();
		String protoType = combos[0];
		for(int i=0; i<combos.length; i++)
		{
			phaseBox.addItem(combos[i]);
			protoType = (combos[i].length() > protoType.length()) ? combos[i] : protoType;
		}
		
		phaseBox.setPrototypeDisplayValue(protoType+"M");
		
		// set currently selected 
		phaseBox.setSelectedItem(phase.getSeasonType() + " " +phase.getPhaseType());
		
		// set if we can display 'bc' years
		if(original.getBCYearsAllowed())
		{
			year.setMinimum(-9999);	// 9999 BC is earliest
		}
		else
		{
			year.setMinimum(1);	// no earlier than 1 AD
		}
		
		// set year
		year.setValue(phase.getYear());
		
		// set spinners
		setSpinner(vcSC, original.getNumSCForVictory(), 1, original.getSupplyCenters().length);
		setSpinner(vcSCChange, original.getMaxYearsNoSCChange(), 0, 9999);
		setSpinner(vcDuration, original.getMaxGameTimeYears(), 0, 9999);
	}// resetData()
	
	
	/** Layout the panel */
	private void makeLayout()
	{
		int w1[] = { BORDER, 15, 0, 0, BORDER };
		int h1[] = { BORDER, 0,10, 0,5, 0,20, 0,5, 0,5, 0,5, 0,5, 0, 0, 5, 0, BORDER };
		
		// create 'minipanels': these put labels and spinners horizontally adjacent
		JPanel timePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
		timePanel.add(phaseBox);
		timePanel.add(year);
		
		JPanel vc1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
		vc1.add(vcSC);
		vc1.add(new JLabel( Utils.getLocalString(LABEL_VC_SC_REQ) ));
		
		JPanel vc2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
		vc2.add(vcSCChange);
		vc2.add(new JLabel( Utils.getLocalString(LABEL_VC_SC_NOCHANGE) ));
		
		JPanel vc3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
		vc3.add(vcDuration);
		vc3.add(new JLabel( Utils.getLocalString(LABEL_VC_DURATION) ));
		
		
		// higlayout
		HIGLayout l1 = new HIGLayout(w1, h1);
		l1.setColumnWeight(4, 1);
		l1.setRowWeight(16, 1);
		
		setLayout(l1);
		HIGConstraints c = new HIGConstraints();
		
		add(introText, c.rcwh(2,2,3,1,"lrtb"));
		
		add(new GradientJLabel(Utils.getLocalString(LABEL_TIME)), c.rcwh(4,2,2,1,"lr"));
		add(timePanel, c.rc(6,3,"l"));
		
		add(new GradientJLabel(Utils.getLocalString(LABEL_VC)), c.rcwh(8,2,2,1,"lr"));
		add(vc1, c.rc(10,3,"l"));
		add(vc2, c.rc(12,3,"l"));
		add(vc3, c.rc(14,3,"l"));
		
		add(new JSeparator(), c.rcwh(17,2,3,1,"lr"));
		
		add(reset, c.rcwh(19,2,2,1,"l"));		
	}// makeLayout()
	
	
	/** 
	*	Creates a custom spinner. Custom spinners have no commas in the numbers, 
	* 	and cannot be negative. 0 is acceptable. Maximum is set to 9999 by default. 
	*	<p>
	*	useSeparator: determine if grouping separator is used for numbers.
	*/
	private JSpinner makeCustomSpinner(boolean useSeparator)
	{
		SpinnerNumberModel model = new SpinnerNumberModel(0, 0, 9999, 1); 
		JSpinner spinner = new JSpinner(model);
		new JSpinner.NumberEditor(spinner, "0000");
		
		if(!useSeparator)
		{
			// remove comma (grouping separator)
			((JSpinner.NumberEditor) spinner.getEditor()).getFormat().setGroupingUsed(false);
		}
		
		return spinner;
	}// makeCustomSpinner()
	
	/** Conveniently sets spinner values & handles any details */
	private void setSpinner(JSpinner spinner, int value, int min, int max)
	{
		SpinnerNumberModel snn = (SpinnerNumberModel) spinner.getModel();
		snn.setMinimum(new Integer(min));
		snn.setMaximum(new Integer(max));
		snn.setValue(new Integer(value));
	}// setSpinner()
	
	/** Convenience method: get int from spinner */
	private int getSpinnerValue(JSpinner spinner)
	{
		return ((Integer) spinner.getValue()).intValue();
	}// getSpinnerValue()
	
	/** Get the tab name. */
	public String getTabName()
	{
		return Utils.getLocalString(TAB_NAME);
	}// getTabName()

	/** The Variant has Changed. */
	public void variantChanged(Variant variant)
	{
		// store passed reference, but modify the cloned version
		original = variant;
		try
		{
			current = (Variant) variant.clone();
		}
		catch(CloneNotSupportedException e)
		{
			throw new IllegalStateException(e.getMessage());
		}
		
		resetData();
		revalidate();
	}// variantChanged()
	
	/** The Enabled status has Changed. */
	public void enablingChanged(boolean enabled)
	{
		setEnabled(enabled);
	}// enablingChanged()
	
}// class NGDStartOptions
