package com.baselet.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import com.baselet.control.Constants;
import com.umlet.language.FieldOptions;
import com.umlet.language.MethodOptions;
import com.umlet.language.SignatureOptions;
import com.umlet.language.sorting.SortOptions;

@SuppressWarnings("serial")
public class GenerateOptionPanel extends JDialog {

	private static GenerateOptionPanel optionpanel;
	
	private JCheckBox packageInfo;
	private ButtonGroup fields;
	private ButtonGroup methods;
	private ButtonGroup signatures;
	private ButtonGroup sortings;
	
	private static final String okButton = "Ok";
	private static final String cancelButton = "Cancel";
	
	private GenerateOptionPanel() {
		Container content = this.getContentPane();
		
		content.add(createOptionPanel(), BorderLayout.CENTER);
		content.add(createButtonPanel(), BorderLayout.SOUTH);
		this.setTitle("Import Details");
		this.pack();
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		this.setLocation(screenSize.width/2 - this.getWidth()/2, screenSize.height/2 - this.getWidth()/2);
	}

	private JPanel createOptionPanel() {
		JPanel optionPanel = new JPanel();
		optionPanel.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		
		packageInfo = new JCheckBox("Show package");
		packageInfo.setSelected(true);
		optionPanel.add(packageInfo, layout(c, 0, 0));
		
		fields = createButtonGroup(FieldOptions.values());
		optionPanel.add(createSubPanel("Show fields", fields), layout(c, 0, 1));
		
		methods = createButtonGroup(MethodOptions.values());
		optionPanel.add(createSubPanel("Show methods", methods), layout(c, 1, 1));
		
		signatures = createButtonGroup(SignatureOptions.values());
		optionPanel.add(createSubPanel("Show signatures", signatures), layout(c, 0, 2));
		
		sortings = createButtonGroup(SortOptions.values());
		optionPanel.add(createSubPanel("Sorting", sortings), layout(c, 1, 2));
		
		optionPanel.validate();
		return optionPanel;
	}

	private <E extends Enum<E>> ButtonGroup createButtonGroup(E[] values) {
		ButtonGroup group = new ButtonGroup();
		for (E value: values) {
			JRadioButton button = new JRadioButton(value.toString());
			button.setActionCommand(value.toString());
			group.add(button);
		}
		return group;
	}
	
	private GridBagConstraints layout(GridBagConstraints c, int gridx, int gridy) {
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridx = gridx;
		c.gridy = gridy;
		return c;
	}
	
	private JPanel createSubPanel(String title, ButtonGroup group) {
		Enumeration<AbstractButton> e = group.getElements();
		JPanel panel = new JPanel();
		panel.setLayout(new GridLayout(0, 1));
		panel.setBorder(BorderFactory.createTitledBorder(title));
		while (e.hasMoreElements()) {
			panel.add(e.nextElement());
		}
		return panel;
	}

	private JPanel createButtonPanel() {
		CancelOkListener listener = new CancelOkListener();
		JButton button_ok = new JButton(okButton);
		button_ok.setActionCommand(okButton);
		button_ok.addActionListener(listener);
		JButton button_cancel = new JButton(cancelButton);
		button_cancel.setActionCommand(cancelButton);
		button_cancel.addActionListener(listener);

		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
		buttonPanel.add(Box.createHorizontalGlue());
		buttonPanel.add(button_cancel);
		buttonPanel.add(Box.createRigidArea(new Dimension(20, 0)));
		buttonPanel.add(button_ok);
		buttonPanel.add(Box.createHorizontalGlue());
		buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
		
		return buttonPanel;
	}

	public static GenerateOptionPanel getInstance() {
		if (optionpanel == null) optionpanel = new GenerateOptionPanel();
		return optionpanel;
	}
	
	private class CancelOkListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			optionpanel.setVisible(false);
			if (e.getActionCommand().equals(okButton)) {
				Constants.generateClassPackage = packageInfo.isSelected();
				Constants.generateClassFields = FieldOptions.getEnum(fields.getSelection().getActionCommand().toString());
				Constants.generateClassMethods = MethodOptions.getEnum(methods.getSelection().getActionCommand().toString());
				Constants.generateClassSignatures = SignatureOptions.getEnum(signatures.getSelection().getActionCommand().toString());
				Constants.generateClassSortings = SortOptions.getEnum(sortings.getSelection().getActionCommand().toString());
			}
		}
	}

	public void showPanel() {
		packageInfo.setSelected(Constants.generateClassPackage);
		setSelectedRadioButton(fields, Constants.generateClassFields);
		setSelectedRadioButton(methods, Constants.generateClassMethods);
		setSelectedRadioButton(signatures, Constants.generateClassSignatures);
		setSelectedRadioButton(sortings, Constants.generateClassSortings);
		this.setVisible(true);
		this.toFront();
	}

	private <E extends Enum<E>> void setSelectedRadioButton(ButtonGroup group, E value) {
		Enumeration<AbstractButton> buttons = group.getElements();
		while(buttons.hasMoreElements()) {
			AbstractButton button = buttons.nextElement();
			if (button.getActionCommand().equals(value.toString())) {
				button.setSelected(true);
			}
		}
	}
}
