
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.Container;
import java.awt.Component;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;

import dirk_krause.jtools.ComponentSizer;
import dirk_krause.jtools.GuiController;
import dirk_krause.jtools.SelfPositioningDialog;
import dirk_krause.jtools.GbcMaker;
import dirk_krause.jtools.StringTool;
import dirk_krause.jtools.ColorShowArea;

public class Png2PdfDialog extends SelfPositioningDialog
	implements ActionListener, WindowListener, ItemListener
{
	protected int b = 5;
	protected Png2PdfController ppc = null;
	protected ActionListener a = null;
	protected ActionListener ccal = null;
	protected ItemListener mixl = null;
	protected ItemListener masl = null;
	protected ItemListener alpl = null;
	protected JButton bOK = null;
	protected JButton bCancel = null;
	protected JComboBox cbPdfVersion = null;
	protected JCheckBox cbMakeMode = null;
	protected JCheckBox cbInterpolation = null;
	protected JCheckBox cbMix = null;
	protected ColorShowArea csa = null;
	protected JCheckBox cbPrefer = null;
	protected JCheckBox cbMask = null;
	protected JCheckBox cbInverted = null;
	protected JCheckBox cbAlpha = null;
	protected JCheckBox cbTransparency = null;
	protected JButton bDefaults = null;
	protected JCheckBox cbShowFilenames = null;
	
	protected boolean isCorrecting = false;
	
	protected synchronized boolean startCorrection()
	{
		boolean back = false;
		if(!isCorrecting) {
			isCorrecting = true; back = true;
		}
		return back;
	}
	
	protected synchronized void finishCorrection()
	{
		isCorrecting = false;
	}
	
	class ColorChangerActionListener implements ActionListener
	{
		Component parent;
		public void actionPerformed(ActionEvent e)
		{
			Color newColor = JColorChooser.showDialog(
				parent, theTexts[15], csa.getColor()
			);
			if(newColor != null) {
				csa.setColor(newColor);
			}
		}
		public ColorChangerActionListener(Component jp)
		{
			parent = jp;
		}
	}
	
	class MixListener implements ItemListener
	{
		public void itemStateChanged(ItemEvent e)
		{
			if(startCorrection()) {
				if(cbMix.isSelected()) {
					if(cbAlpha.isSelected()) {
						cbAlpha.setSelected(false);
						cbMask.setSelected(true);
					}
				}
				finishCorrection();
			}
		}
	}
	
	class MaskListener implements ItemListener
	{
		public void itemStateChanged(ItemEvent e)
		{
			if(startCorrection()) {
				if(cbMask.isSelected()) {
					if(cbAlpha.isSelected()) {
						cbAlpha.setSelected(false);
						cbMix.setSelected(true);
					}
				}
				finishCorrection();
			}
		}
	}
	
	class AlphaListener implements ItemListener
	{
		public void itemStateChanged(ItemEvent e)
		{
			if(startCorrection()) {
				if(cbAlpha.isSelected()) {
					if(cbMix.isSelected()) {
						cbMix.setSelected(false);
					}
					if(cbMask.isSelected()) {
						cbMask.setSelected(false);
					}
				}
				finishCorrection();
			}
		}
	}
	
	public static final String[] theTexts = {
		/*  0 */ "Png2pdf Options",
		/*  1 */ "General options",
		/*  2 */ "Image interpolation",
		/*  3 */ "Alpha channel handling",
		/*  4 */ "PDF format version: ",
		/*  5 */ "Run in \"make\" mode (check modification timestamps)",
		/*  6 */ "Set interpolation flag",
		/*  7 */ "Mix against a background color",
		/*  8 */ "Choose default background color: ",
		/*  9 */ "   ",
		/* 10 */ "Prefer specified default color over background color chunk",
		/* 11 */ "Create image mask",
		/* 12 */ "Use inverted mask levels",
		/* 13 */ "Write alpha channel to output",
		/* 14 */ "Input alpha channel expresses transparency",
		/* 15 */ "Choose default background color",
		/* 16 */ "Show file names while processing"
	};
	public static final String[] buttonTexts = {
		/*  0 */ "OK",
		/*  1 */ "Cancel",
		/*  2 */ "Defaults",
	};
	public static final String[] pdfVersions = {
		"1.2", "1.3", "1.4"
	};
	
	public Png2PdfDialog(JFrame p, GuiController gc, Png2PdfController pc, ActionListener al)
	{
		super(p);
		b = gc.getBorder();
		ppc = pc;
		a = al;
		setTitle(theTexts[0]);
		Container cp = getContentPane();
		GridBagLayout gbl = new GridBagLayout();
		cp.setLayout(gbl);
		GridBagConstraints gbc = null;
		JPanel jp = null;
		GbcMaker gbcm = new GbcMaker(4,1,b);
		// general options panel
		jp = new JPanel();
		setGeneralOptionsPanel(jp);
		gbc = gbcm.create(0,0,1,1);
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(jp, gbc);
		cp.add(jp);
		// interpolation panel
		jp = new JPanel();
		setInterpolationPanel(jp);
		gbc = gbcm.create(1,0,1,1);
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(jp, gbc);
		cp.add(jp);
		// alpha panel
		jp = new JPanel();
		setAlphaPanel(jp);
		gbc = gbcm.create(2,0,1,1);
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbl.setConstraints(jp, gbc);
		cp.add(jp);
		// button panel
		jp = new JPanel();
		setButtonPanel(jp);
		gbc = gbcm.create(3,0,1,1);
		gbl.setConstraints(jp, gbc);
		cp.add(jp);
		// and finish setup
		csa.setToolTipText(theTexts[15]);
		pack();
		addWindowListener(this);
		ccal = new ColorChangerActionListener(this);
		csa.addActionListener(ccal);
		mixl = new MixListener();
		cbMix.addItemListener(mixl);
		masl = new MaskListener();
		cbMask.addItemListener(masl);
		alpl = new AlphaListener();
		cbAlpha.addItemListener(alpl);
		cbPdfVersion.addItemListener(this);
		controller_to_dialog();
	}
	
	protected void setAlphaPanel(JPanel jp)
	{
		jp.setBorder(BorderFactory.createTitledBorder(theTexts[3]));
		GridBagLayout gbl = new GridBagLayout();
		jp.setLayout(gbl);
		GbcMaker gbcm = new GbcMaker(7, 4, b);
		GridBagConstraints gbc = null;
		cbTransparency = new JCheckBox(theTexts[14]);
		gbc = gbcm.create(0, 0, 1, 3);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbTransparency, gbc);
		jp.add(cbTransparency);
		cbMix = new JCheckBox(theTexts[7]);
		gbc = gbcm.create(1, 0, 1, 3);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbMix, gbc);
		jp.add(cbMix);
		JLabel l = new JLabel(theTexts[9]);
		gbc =  gbcm.create(2,0,1,1);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(l, gbc);
		jp.add(l);
		l = new JLabel(theTexts[8]);
		gbc = gbcm.create(2, 1, 1, 1);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(l, gbc);
		jp.add(l);
		csa = new ColorShowArea();
		gbc = gbcm.create(2, 2, 1, 1);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(csa, gbc);
		jp.add(csa);
		JPanel dp = gbcm.createDummyPanel();
		gbc = gbcm.createDummyGbc(2,3,1,1);
		gbl.setConstraints(dp, gbc);
		jp.add(dp);
		cbPrefer = new JCheckBox(theTexts[10]);
		gbc = gbcm.create(3,1,1,2);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbPrefer, gbc);
		jp.add(cbPrefer);
		cbMask = new JCheckBox(theTexts[11]);
		gbc = gbcm.create(4,0,1,3);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbMask, gbc);
		jp.add(cbMask);
		cbInverted = new JCheckBox(theTexts[12]);
		gbc = gbcm.create(5,1,1,2);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbInverted, gbc);
		jp.add(cbInverted);
		cbAlpha = new JCheckBox(theTexts[13]);
		gbc = gbcm.create(6,0,1,3);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbAlpha, gbc);
		jp.add(cbAlpha);
	}
	
	protected void setInterpolationPanel(JPanel jp)
	{
		jp.setBorder(BorderFactory.createTitledBorder(theTexts[2]));
		GridBagLayout gbl = new GridBagLayout();
		jp.setLayout(gbl);
		GbcMaker gbcm = new GbcMaker(1, 2, b);
		GridBagConstraints gbc = null;
		cbInterpolation = new JCheckBox(theTexts[6]);
		gbc = gbcm.create(0,0,1,1);
		gbl.setConstraints(cbInterpolation, gbc);
		jp.add(cbInterpolation);
		JPanel dp = gbcm.createDummyPanel();
		gbc = gbcm.createDummyGbc(0,1,1,1);
		gbl.setConstraints(dp, gbc);
		jp.add(dp);
	}
	
	protected void setGeneralOptionsPanel(JPanel jp)
	{
		jp.setBorder(BorderFactory.createTitledBorder(theTexts[1]));
		GridBagLayout gbl = new GridBagLayout();
		jp.setLayout(gbl);
		GbcMaker gbcm = new GbcMaker(3, 3, b);
		GridBagConstraints gbc = null;
		JLabel jl = new JLabel(theTexts[4]);
		gbc = gbcm.create(0,0,1,1);
		gbl.setConstraints(jl, gbc);
		jp.add(jl);
		cbPdfVersion = new JComboBox();
		for(int i = 0; i < pdfVersions.length; i++) {
			cbPdfVersion.addItem(pdfVersions[i]);
		}
		cbPdfVersion.setSelectedIndex(0);
		gbc = gbcm.create(0,1,1,1);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbPdfVersion, gbc);
		jp.add(cbPdfVersion);
		JPanel dp = gbcm.createDummyPanel();
		gbc = gbcm.createDummyGbc(0, 2, 1, 1);
		gbl.setConstraints(dp, gbc);
		jp.add(dp);
		cbMakeMode = new JCheckBox(theTexts[5]);
		gbc = gbcm.create(1,0,1,2);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbMakeMode, gbc);
		jp.add(cbMakeMode);
		cbShowFilenames = new JCheckBox(theTexts[16]);
		gbc = gbcm.create(2, 0, 1, 2);
		gbc.anchor = GridBagConstraints.WEST;
		gbl.setConstraints(cbShowFilenames, gbc);
		jp.add(cbShowFilenames);
	}
	
	protected void setButtonPanel(JPanel jp) 
	{
		jp.setLayout(new BoxLayout(jp, BoxLayout.LINE_AXIS));
		bOK = new JButton(buttonTexts[0]);
		bOK.addActionListener(this);
		bCancel = new JButton(buttonTexts[1]);
		bCancel.addActionListener(this);
		bDefaults = new JButton(buttonTexts[2]);
		bDefaults.addActionListener(this);
		ComponentSizer cs = new ComponentSizer();
		cs.getComponentSize(bOK); cs.getComponentSize(bCancel);
		cs.getComponentSize(csa); cs.getComponentSize(bDefaults);
		cs.setComponentSize(bOK); cs.setComponentSize(bCancel);
		cs.setComponentSize(csa); cs.setComponentSize(bDefaults);
		jp.add(Box.createHorizontalGlue());
		jp.add(bOK);
		jp.add(Box.createRigidArea(new Dimension(b, b)));
		jp.add(bCancel);
		jp.add(Box.createRigidArea(new Dimension(b, b)));
		jp.add(bDefaults);
		jp.add(Box.createHorizontalGlue());
	}
	
	public void cleanup()
	{
		cbPdfVersion.removeItemListener(this);
		cbMix.removeItemListener(mixl);
		mixl = null;
		cbMask.removeItemListener(masl);
		masl = null;
		cbAlpha.removeItemListener(alpl);
		alpl = null;
		csa.removeActionListener(ccal);
		ccal = null;
		removeWindowListener(this);
		bOK.removeActionListener(this);
		bCancel.removeActionListener(this);
	}
	
	public void controller_to_dialog()
	{
		if(startCorrection()) {
			int i = ppc.getPdfVersion();
			if(i < 0) i = 0; if(i > 2) i = 2;
			cbPdfVersion.setSelectedIndex(i);
			cbMakeMode.setSelected(ppc.getMakeMode());
			cbInterpolation.setSelected(ppc.getInterpolate());
			cbTransparency.setSelected(ppc.getAlphaTrans());
			cbMix.setSelected(ppc.getMix());
			csa.setColor(ppc.getMixColor());
			cbPrefer.setSelected(ppc.getPreferMyColor());
			cbMask.setSelected(ppc.getMask());
			cbInverted.setSelected(ppc.getMaskInverted());
			cbAlpha.setSelected(ppc.getAlpha());
			cbShowFilenames.setSelected(ppc.getShowFilenames());
			finishCorrection();
		}
		correct_dialog();
	}
	
	public void dialog_to_controller()
	{
		int i = cbPdfVersion.getSelectedIndex();
		if(i < 0) i = 0; if(i > 2) i = 2;
		ppc.setPdfVersion(i);
		ppc.setMakeMode(cbMakeMode.isSelected());
		ppc.setInterpolate(cbInterpolation.isSelected());
		ppc.setAlphaTrans(cbTransparency.isSelected());
		ppc.setMix(cbMix.isSelected());
		ppc.setMixColor(csa.getColor());
		ppc.setPreferMyColor(cbPrefer.isSelected());
		ppc.setMask(cbMask.isSelected());
		ppc.setMaskInverted(cbInverted.isSelected());
		ppc.setAlpha(cbAlpha.isSelected());
		ppc.setShowFilenames(cbShowFilenames.isSelected());
	}
	
	protected void setDefaults()
	{
		if(startCorrection()) {
			cbMakeMode.setSelected(true);
			cbPdfVersion.setSelectedIndex(2);
			cbInterpolation.setSelected(true);
			cbMix.setSelected(false);
			cbTransparency.setSelected(false);
			csa.setColor(new Color(255,255,255));
			cbPrefer.setSelected(false);
			cbMask.setSelected(false);
			cbInverted.setSelected(false);
			cbAlpha.setSelected(true);
			cbMask.setEnabled(true);
			cbAlpha.setEnabled(true);
			cbInterpolation.setEnabled(true);
			cbShowFilenames.setSelected(false);
			finishCorrection();
		}
	}
	
	protected void disable_interpolation()
	{
		cbInterpolation.setSelected(false);
		cbInterpolation.setEnabled(false);
	}
	
	protected void enable_interpolation()
	{
		cbInterpolation.setEnabled(true);
	}
	
	protected void allow_alpha(boolean m, boolean i, boolean a)
	{
		if(a) {
			cbAlpha.setEnabled(true);
			if(cbAlpha.isSelected()) {
				if(cbMask.isSelected()) {
					cbMask.setSelected(false);
				}
				if(cbMix.isSelected()) {
					cbMix.setSelected(false);
				}
			}
		} else {
			if(cbAlpha.isSelected()) {
				cbAlpha.setSelected(false);
				if(i) {
					cbMask.setSelected(true);
				}
			}
			cbAlpha.setEnabled(false);
		}
		if(i) {
			cbMask.setEnabled(true);
		} else {
			if(cbMask.isSelected()) {
				cbMask.setSelected(false);
				cbMix.setSelected(true);
			}
			cbMask.setEnabled(false);
		}
		if(m) {
			cbMix.setEnabled(true);
		} else {
			if(cbMix.isSelected()) {
				cbMix.setSelected(false);
			}
			cbMix.setEnabled(false);
		}
	}
	
	public void correct_dialog()
	{
		if(startCorrection()) {
			switch(cbPdfVersion.getSelectedIndex()) {
			case Png2PdfController.PDF_VERSION_12: {
				disable_interpolation();
				allow_alpha(true, false, false);
			} break;
			case Png2PdfController.PDF_VERSION_13: {
				enable_interpolation();
				allow_alpha(true, true, false);
			} break;
			case Png2PdfController.PDF_VERSION_14: {
				enable_interpolation();
				allow_alpha(true, true, true);
			} break;
			}
			finishCorrection();
		}
	}
	
	public void actionPerformed(ActionEvent e)
	{
		switch(StringTool.getArrayIndex(buttonTexts, e.getActionCommand())) {
		case 0: {	// OK
			setVisible(false);
			dialog_to_controller();
			controller_to_dialog();
			correct_dialog();
			if(a != null) {
				ActionEvent myEvent =
				new ActionEvent(this,ActionEvent.ACTION_PERFORMED, Png2PdfWindow.actionCmd[5]);
				a.actionPerformed(myEvent);
			}
		} break;
		case 1: {	// Cancel
			setVisible(false);
			controller_to_dialog();
			correct_dialog();
		} break;
		case 2: {
			setDefaults();
		} break;
		}
	}
	
	public void itemStateChanged(ItemEvent e)
	{
		correct_dialog();
		repaint();
	}
	
	public void windowClosing(WindowEvent e)
    {
		setVisible(false);
		controller_to_dialog();
    }
	public void windowActivated(WindowEvent e) {}
	public void windowClosed(WindowEvent e) {}
	public void windowDeactivated(WindowEvent e) {}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}
}
