package adecWatt.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

import misc.DimensionDouble;
import misc.Util;

// sauver dans une liste de preview

@SuppressWarnings ("serial") public class JPreviewImp extends JPanel implements ActionListener {

    // ========================================
    static public final String
	actionPortrait		= "Portrait",
	actionLandscape		= "Landscape",
	actionAddZone		= "AddZone",
	actionAddPoster		= "AddPoster",
	actionAddPatch		= "AddPatch",
	actionRemoveZone	= "RemoveZone",
	actionTurnLeft		= "TurnLeft",
	actionTurnRight		= "TurnRight",
	actionCircuit		= "Circuit";

    static public final List<String>
	previewButtonsNames	= Arrays.asList (//actionPortrait, actionLandscape,
						 actionAddZone, actionAddPoster, actionAddPatch, actionRemoveZone,
						 actionTurnLeft, actionTurnRight);
    static public final List<String>
	previewActionsNames	= Arrays.asList (//actionPortrait, actionLandscape,
						 actionAddZone, actionAddPoster, actionAddPatch, actionRemoveZone,
						 actionTurnLeft, actionTurnRight, actionCircuit);
    @SuppressWarnings ("unchecked")
    static public final Hashtable<String, Method> actionsMethod =
	Util.collectMethod (JPreviewImp.class, previewActionsNames);

    public void  actionPerformed (ActionEvent e) {
	Util.actionPerformed (actionsMethod, e, this);
    }
    public void actionPortrait () {
	setLandscape (false);
    }
    public void actionLandscape () {
	setLandscape (true);
    }
    public void actionAddZone () {
	Color color = getColor ();
	JZones.Zone selectedZone = preview.getSelectedZone ();
	JZones.Zone newZone = (selectedZone != null && selectedZone.getPair () != null) ?
	    workspace.addZone (color, selectedZone.getPair ().getRectangle ()) :
	    workspace.addZone (color);
	preview.addZone (newZone, null);
	preview.selectLastZone ();
	actionCircuit ();
    }
    public void actionAddPoster () {
	if (posterImage == null)
	    return;
	Color color = getColor ();
	preview.addZone (color, posterImage);
	preview.selectLastZone ();
    }
    public void actionAddPatch () {
	if (patchImage == null)
	    return;
	Color color = getColor ();
	preview.addZone (color, patchImage);
	preview.selectLastZone ();
    }
    public void actionRemoveZone () {
	JZones.Zone selectedZone = preview.getSelectedZone ();
	if (selectedZone == null)
	    return;
	preview.removeZone (selectedZone);
	workspace.removeZone (selectedZone.getPair ());
    }
    public void actionTurnLeft () {
	preview.turnZoneLeft ();
    }
    public void actionTurnRight () {
	preview.turnZoneRight ();
    }
    public void actionCircuit () {
	JZones.Zone selectedZone = preview.getSelectedZone ();
	if (selectedZone == null || !selectedZone.hasPair () || workspaceImageNoCircuit == null)
	    return;
	boolean printCircuit = jCheckBoxCircuit.isSelected ();
	if (printCircuit) {
	    noPrintCircuit.remove (selectedZone);
	    selectedZone.setImage (workspaceImage);
	} else {
	    noPrintCircuit.add (selectedZone);
	    selectedZone.setImage (workspaceImageNoCircuit);
	}
    }
    public void updateCircuit (JZones.Zone selectedZone) {
	if (selectedZone == null || !selectedZone.hasPair () || workspaceImageNoCircuit == null)
	    return;
	jCheckBoxCircuit.setSelected (!noPrintCircuit.contains (selectedZone));
    }

    // ========================================
    JSplitPane jSplitPane;
    JZones workspace, preview;
    HashSet<JZones.Zone> noPrintCircuit = new HashSet<JZones.Zone> ();
    JCheckBox jCheckBoxCircuit;
    BufferedImage workspaceImage, workspaceImageNoCircuit, posterImage, patchImage;
    
    public JPreviewImp (DimensionDouble workspaceSize, DimensionDouble pageSize,
			BufferedImage workspaceImage, BufferedImage workspaceImageNoCircuit,
			BufferedImage posterImage, BufferedImage patchImage,
			int maxSide) {
	this (new JZones (workspaceSize, maxSide), new JZones (pageSize, maxSide));
	this.workspaceImage = workspaceImage;
	this.workspaceImageNoCircuit = workspaceImageNoCircuit;
	this.posterImage = posterImage;
	this.patchImage = patchImage;
	workspace.setBackground (workspaceImage);
    }
    public JPreviewImp (DimensionDouble workspaceSize, DimensionDouble pageSize, int maxSide) {
	this (new JZones (pageSize, maxSide), new JZones (workspaceSize, maxSide));
    }
    private JPreviewImp (JZones workspace, JZones preview) {
	super (new BorderLayout ());
	this.preview = preview;
	this.workspace = workspace;
	preview.setCornerSelection (false);
	preview.setCreateZone (false);
	jSplitPane = Util.getJSplitPane (JSplitPane.HORIZONTAL_SPLIT, getJZonesFrame (workspace), getJZonesFrame (preview));
	add (jSplitPane, BorderLayout.CENTER);
	workspace.stateNotifier.addUpdateObserver (this, JZones.BroadcastSelectedLocationChange, JZones.BroadcastSelectedRateChange);
	workspace.stateNotifier.addMsgObserver (this, JZones.BroadcastCreateZone, JZones.BroadcastSelectedChange);
	preview.stateNotifier.addMsgObserver (this, JZones.BroadcastSelectedChange);
	JPanel menuBar = new JPanel ();
	menuBar.setLayout (new BoxLayout (menuBar, BoxLayout.X_AXIS));
	Util.addIconButton (previewButtonsNames, this, menuBar);
	jCheckBoxCircuit = Util.newCheckIcon (actionCircuit, this, true);
	menuBar.add (jCheckBoxCircuit);
	Util.unBoxButton (menuBar);
	add (menuBar, BorderLayout.NORTH);
    }
    public JPanel getJZonesFrame (JZones jZones) {
	JPanel jPanel = new JPanel (new BorderLayout ());
	jPanel.add (Util.getJScrollPane (jZones), BorderLayout.CENTER);
	jPanel.add (jZones.new SizeSlider (), BorderLayout.SOUTH);
	return jPanel;
    }

    static public final Color [] rainbow;
    static {
	int nbColors = 7;
	rainbow = new Color[nbColors];
	for (int i = 0; i < nbColors; i++)
	    rainbow[i] = new Color (Color.HSBtoRGB (((float)i)/nbColors, 1, 1));
    }
    int rainbowIndex = -1;
    public Color getColor () {
	rainbowIndex = (rainbowIndex+1)%rainbow.length;
	return rainbow [rainbowIndex];
    }
    public void displayCreateZone (Object... objects) {
	if (objects[0] == null)
	    return;
	Rectangle2D.Double area = (Rectangle2D.Double) objects[0];
	Color color = getColor ();
	preview.addZone (workspace.addZone (color, area), null);
	preview.selectLastZone ();
	actionCircuit ();
    }
    public void displaySelectedChange (Object... objects) {
	if (objects[0] == null)
	    return;
	JZones src = (JZones) objects[0];
	JZones.Zone selectZone = (JZones.Zone) objects[1];
	if (selectZone == null) {
	    JZones dst = src == workspace ? preview : workspace;
	    dst.selectZoneQuiet (null);
	    return;
	}
	if (src == preview) {
	    updateCircuit (selectZone);
	    workspace.selectZoneQuiet (selectZone.getPair ());
	    return;
	}
	JZones.Zone pair = preview.findPair (selectZone);
	updateCircuit (pair);
	preview.selectZoneQuiet (pair);
    }
    public void updateSelectedRateChange () {
	JZones.Zone selectedZone = preview.getSelectedZone ();
	if (selectedZone == null)
	    return;
	selectedZone.updatePairRate ();
    }
    public void updateSelectedLocationChange () {
	preview.repaint ();
    }
    public void setLandscape (boolean landscape) {
	double currentPrevRate = preview.getScale ();
	double currentWorkRate = workspace.getScale ();
	if (!preview.setLandscape (landscape))
	    return;
	preview.resetScale ();
	workspace.resetScale ();
	//jSplitPane.resetToPreferredSizes ();
	Util.packWindow (this);
	preview.setScale (currentPrevRate);
	workspace.setScale (currentWorkRate);
    }

    // ========================================
    static public void main (String[] args) {
	try {
	    misc.Config.setPWD (JPreviewImp.class);
	    BufferedImage workspaceImage = javax.imageio.ImageIO.read (new java.io.File ("/home/felix/perso/adecWatt/ws/exemplePrint.png"));

	    DimensionDouble pageSize = new DimensionDouble (21, 29.7);
	    DimensionDouble workspaceSize = new DimensionDouble (25, 34);
	    int maxSide = 200;
	    JPreviewImp jPreviewImp = new JPreviewImp (workspaceSize, pageSize, workspaceImage, null, workspaceImage, workspaceImage, maxSide);
	    Util.newJFrame ("test", jPreviewImp, true);
	    jPreviewImp.actionAddZone ();
	} catch (Exception e) {
	    e.printStackTrace ();
	}
    }

    // ========================================
}
