/*
 * ECatalog is a database front-end, with two main features:
 * 1. Use of preferences
 *  A preference-based approach, where the user is allowed to define the importance of each criterion.
 *  Then the items are ranked accordingly to his criteria.
 * 2. Trade-off analysis
 *  A cooperative database approach, where the system "argues" with the user about his criteria.
 *  When there are no matching items, the system explains the minimal conflicting set and
 *  give some possible strong and weak relaxations about his criteria.
 * This package also containts the software and the set-up details used for our User Study,
 * comparing the use or not of the two previous features mentioned above.
 *
 * Copyright (C) 2006 David Portabella Clotet, Artificial Intelligence Laboratory, EPFL
 * 
 * This file is part of ecatalog-1.0.zip
 * 
 * ECatalog is free software and a free user study set-up;
 * 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.
 * 
 * ECatalog 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 ECatalog; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * @version 1.0
 * @author David Portabella
 * To contact the author:
 * email: david@portabella.name and david.portabella@epfl.ch
 * 
 * More information about ECatalog:
 *  http://sourceforge.net/projects/ecatalog/
 *  http://icwww.epfl.ch/~portabel/ecatalogs/
 */

package ecatalog.gui.criteriaSelection;

import ecatalog.gui.MainGui;
import ecatalog.ECatalog;
import ecatalog.db.*;

import org.w3c.dom.Element;

import utils.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import java.util.Vector;

import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Arrays;
import java.util.Comparator;

import java.sql.SQLException;

import dpc.utils.ArrayConverter;
import dpc.utils.DebugUtil;

import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;


class BooleanAttributeConstraintGui extends AttributeConstraintGui {
    EqualConstraint constraint;
    BooleanAttribute attribute;
    String label = "boolean";

    JRadioButton yesButton, noButton;
    JButton clearButton;

    String yesString = "yes", noString = "no";
    //enum Value {YES, NO};

    boolean systemChangingFields = false;

    public void configure(Element config, Attribute attribute) {
	configure((BooleanAttribute)attribute);
    }

    public void configure(BooleanAttribute attribute) {
	this.attribute = attribute;
    }

    public void attach(MainGui mainGui, Database db, ECatalog ecatalog, WeightSelector weightSelector) {
	super.attach(mainGui, db, ecatalog, weightSelector);

	constraint = new EqualConstraint(attribute, db, ecatalog.getDefaultWeight(), null);
	db.addConstraint(constraint);

	constraint.update();  //TODO: Fix. Swing calls the JComboBox model and rendered before everything is initialise.
	initGui();
    }

    public void setEnabled(boolean enabled) {
	yesButton.setEnabled(enabled);
	noButton.setEnabled(enabled);

	clearButton.setEnabled((enabled && constraint.areDetailsDefined() == true));
	if (weightSelector != null)
	    weightSelector.setEnabled(enabled);
    }

    public String getConstraintTypeLabel() {
	return label;
    }

    public Constraint getConstraint() {
	return constraint;
    }

    public Attribute getAttribute() {
	return attribute;
    }

    public void reset() {
	constraint.removeDetails();

	//constraint.setWeightToDefault();
	constraint.setWeight(ecatalog.getDefaultWeight());
    }

    public void detach() {
	constraint.removeDetails();
    }

    public void requestFocus() {
	yesButton.requestFocus();  //TODO: ...
    }

    public void update() throws SQLException {
	if (weightSelector != null)
	    weightSelector.update();
	systemChangingFields = true;

	//Select the appropiate button
	if (!constraint.areDetailsDefined()) {
	    clearButton.setEnabled(false); 
	    yesButton.setSelected(false);
	    noButton.setSelected(false);
	} else if (constraint.getValueIndex() == BooleanAttribute.yesIndex) {
	    clearButton.setEnabled(true); 
	    yesButton.setSelected(true);
	    noButton.setSelected(false);
	} else {
	    clearButton.setEnabled(true); 
	    yesButton.setSelected(false);
	    noButton.setSelected(true);
	}

	//Set the analysis information
	if (ecatalog.getConfig().isProspectiveAnalysisDisplayed()) {
	    int numYesItems = constraint.getCurrentNbrCompatibleItemsIfValueSelected(1);
	    int numNoItems = constraint.getCurrentNbrCompatibleItemsIfValueSelected(0);

	    yesButton.setText(yesString + " (" + numYesItems + ")");
	    noButton.setText(noString + " (" + numNoItems + ")");
	} else {
	    yesButton.setText(yesString);
	    noButton.setText(noString);
	}

	
	//set colors, overconstrained or example value
	Color[] colors = new Color[] {Color.black, Color.black};
	if (db.getCurrentNbrSolutions() == 0 && constraint.areDetailsDefined()) {
	    colors[constraint.getValueIndex()] = mainGui.colorOverconstrained;
	} else if (ecatalog.getConfig().isExampleDisplayed() && db.getCurrentNbrSolutions() > 0) {
	    colors[attribute.getCurrentExampleValueIndex()] = mainGui.colorExample;
	}
	yesButton.setForeground(colors[1]);
	noButton.setForeground(colors[0]);

	systemChangingFields = false;
    }

    public void valueClear() {
	if (ecatalog.getLog() != null)
	    ecatalog.getLog().updateConstraint(this, "REMOVE", -1);

	constraint.removeDetails();
	ecatalog.update();
    }

    void selected(boolean value) {
	//quickly unselect the other button. this should be done with GroupButton, but I cannot use it.
	systemChangingFields = true;
	((value == true) ? noButton : yesButton).setSelected(false);
	systemChangingFields = false;

	
	int valueIndex = (value == true) ? BooleanAttribute.yesIndex : BooleanAttribute.noIndex;
	if (ecatalog.getLog() != null)
	    ecatalog.getLog().updateConstraint(this, constraint.areDetailsDefined() ? "MODIFY" : "ADD", valueIndex);
	constraint.setValueIndex(valueIndex);

	ecatalog.update();
    }


    /* Computes the tooltip for the yes button */
    public String getYesNoToolTipText(boolean valueId) {
      	if (!ecatalog.getConfig().isProspectiveAnalysisDisplayed() || !ecatalog.getConfig().isContextualToolTipDisplayed())
	    return null;

	try {
	    int valueIndex = attribute.getValueIndex(valueId);
	    String text = attribute.getConfig().getHelpPrompt() + ".\n";
	    int nbrItems = constraint.getCurrentNbrCompatibleItemsIfValueSelected(valueIndex);

	    if (constraint.areDetailsDefined() && constraint.getValueIndex() == valueIndex) {
		text += "You have defined the criteria \"" + constraint.getWithConstraintString() + "\".\n";

		if (db.getCurrentNbrSolutions() == 0)
		    text += "With all the selected criteria, there are not compatible items.\nYou can see the current TRADEOFFS in the analysis windows.";
		else
		    text += "With all the selected criteria, there are " + db.getCurrentNbrSolutions() + " compatible items.\nIf you remove this criteria, there would be " + constraint.getCurrentNbrCompatibleItemsExcludingThisConstraint() + " compatible items.";
	    } else {
		String actionText = (constraint.areDetailsDefined()) ? "change to" : "select";

		EqualConstraint tmpC = (EqualConstraint)constraint.clone();
		tmpC.setValueIndex(valueIndex);
		text += "If you " + actionText + " this criteria (" + tmpC.getWithConstraintString() + "),\n";

		if (nbrItems > 0) {
		    text += "there would be " + nbrItems + " compatible items.";
		} else {
		    text += "there won't be compatible items.\nYou will see the TRADEOFFS in the analysis window";
		}
	    }

	    ////System.out.println("tooltip " + attribute.id + ".getYesNoToolTipText: " + text);
	    //System.out.println("tooltip " + attribute.id + ".getYesNoToolTipText: " + valueId);
	    return text;
	}
	catch (CloneNotSupportedException e) { 
	    ECatalog.error(e); 
	    throw new Error(); //it is already done, but to avoid the java compiling error
	}
	catch (SQLException e) { 
	    ECatalog.error(e); 
	    throw new Error(); //it is already done, but to avoid the java compiling error
	}
    }

    /*
    public String getDontCareToolTipText() {
      	if (!ecatalog.getConfig().isProspectiveAnalysisDisplayed())
	    return null;

	String text = attribute.getConfig().getHelpPrompt() + ".\n";

	if (constraint.areDetailsDefined())
	    text += "You have defined the criteria \"" + constraint.getWithConstraintString() + "\".\nSelect this option to remove this criteria.\n";

	////System.out.println("tooltip " + attribute.id + ".getDontCareToolTipText: " + text);
	//System.out.println("tooltip " + attribute.id + ".getDontCareToolTipText: dontCare");
	return text;
    }
    */

    void initGui() {
	systemChangingFields = true;
	mainPanel = new JPanel();
	mainPanel.setBackground(Color.white);
	mainPanel.setLayout(new TableLayout(new double[][] {{TableLayout.PREFERRED, 2, TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED},
							    {TableLayout.PREFERRED}}));
	mainPanel.setBackground(Color.WHITE);

	// Create the yes botton
	yesButton = new FixSizeRadioButton(yesString + "(xxxx)") {
		public JToolTip createToolTip() { return MainGui.createToolTip(); }
		public String getToolTipText(MouseEvent event) { return getYesNoToolTipText(true); }
	    };
	yesButton.setToolTipText("...");  //TODO minor: if not, the getToolTipText function is not called. ???

	//yesButton.setBackground(Color.WHITE);
	yesButton.setOpaque(false);
	yesButton.setMaximumSize(yesButton.getPreferredSize());
	yesButton.setMinimumSize(yesButton.getPreferredSize());
	yesButton.setFont(mainGui.font);
	yesButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!systemChangingFields) selected(true); }});
	mainPanel.add(yesButton, new TableLayoutConstraints(0, 0));

	noButton = new FixSizeRadioButton(noString + "(xxxx)") {
		public JToolTip createToolTip() { return MainGui.createToolTip(); }
		public String getToolTipText(MouseEvent event) { return getYesNoToolTipText(false); }
	    };
	noButton.setToolTipText("...");  //TODO minor: if not, the getToolTipText function is not called. ???
	//noButton.setBackground(Color.WHITE);
	noButton.setOpaque(false);
	noButton.setMaximumSize(noButton.getPreferredSize());
	noButton.setMinimumSize(noButton.getPreferredSize());
	noButton.setFont(mainGui.font);
	noButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!systemChangingFields) selected(false); }});
	mainPanel.add(noButton, new TableLayoutConstraints(2, 0));

	clearButton = new AnotherLinkButton("clear");
	clearButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { valueClear(); } });
	mainPanel.add(clearButton, new TableLayoutConstraints(4, 0));

	/*  //It does not work. When the user clicks the clear button, ButtonGroup does not allow to unselect the yes and no button.
	ButtonGroup group = new ButtonGroup();
	group.add(noButton);
	group.add(yesButton);
	*/
	systemChangingFields = false;
    }
}

