package charactermanaj.ui;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.DefaultListModel;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;

import charactermanaj.model.CharacterData;
import charactermanaj.model.PartsSet;
import charactermanaj.util.LocalizedResourcePropertyLoader;

public class ManageFavoriteDialog extends JDialog {

	private static final long serialVersionUID = 1L;

	protected static final String STRINGS_RESOURCE = "strings/managefavoritesdialog";

	private CharacterData characterData;
	
	private DefaultListModel listModel;
	
	private JList list;
	
	private boolean dirty;
	
	public ManageFavoriteDialog(JFrame parent, CharacterData characterData) {
		super(parent, true);
		if (characterData == null) {
			throw new IllegalArgumentException();
		}
		
		setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				onClose();
			}
		});
		
		Properties strings = LocalizedResourcePropertyLoader.getInstance()
				.getLocalizedProperties(STRINGS_RESOURCE);

		setTitle(strings.getProperty("manageFavorites"));
		
		this.characterData = characterData;
		
		characterData.getPartsSets();
		
		Container contentPane = getContentPane();
		contentPane.setLayout(new BorderLayout());
		
		listModel = new DefaultListModel();
		list = new JList(listModel);
		
		AbstractAction actDelete = new AbstractAction(strings.getProperty("remove")) {
			private static final long serialVersionUID = 1L;
			public void actionPerformed(ActionEvent e) {
				onDelete();
			}
		};
		AbstractAction actRename = new AbstractAction(strings.getProperty("rename")) {
			private static final long serialVersionUID = 1L;
			public void actionPerformed(ActionEvent e) {
				onRename();
			}
		};

		JPanel buttonsPanel = new JPanel();
		GridBagLayout gb = new GridBagLayout();
		GridBagConstraints gbc = new GridBagConstraints();
		buttonsPanel.setLayout(gb);
		
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.anchor = GridBagConstraints.EAST;
		gbc.fill = GridBagConstraints.BOTH;
		buttonsPanel.add(new JButton(actDelete), gbc);

		gbc.gridx = 0;
		gbc.gridy = 1;
		buttonsPanel.add(new JButton(actRename), gbc);
		
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.weighty = 1.;
		buttonsPanel.add(Box.createGlue(), gbc);

		
		JPanel panel2 = new JPanel();
		panel2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 42));
		panel2.setLayout(new BorderLayout());
		Action actCancel = new AbstractAction(strings.getProperty("close")) {
			private static final long serialVersionUID = 1L;
			public void actionPerformed(ActionEvent e) {
				onClose();
			}
		};
		JButton btnClose = new JButton(actCancel);
		panel2.add(btnClose, BorderLayout.EAST);

		JScrollPane scr = new JScrollPane(list);
		scr.setBorder(BorderFactory.createEtchedBorder());
		scr.setPreferredSize(new Dimension(300, 150));
		
		contentPane.add(scr, BorderLayout.CENTER);
		contentPane.add(buttonsPanel, BorderLayout.EAST);
		contentPane.add(panel2, BorderLayout.SOUTH);

		JRootPane rootPane = getRootPane();
		rootPane.setDefaultButton(btnClose);
		InputMap im = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
		ActionMap am = rootPane.getActionMap();
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "deleteFav");
		im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "closeManageFavoriteDialog");
		am.put("deleteFav", actDelete);
		am.put("closeManageFavoriteDialog", actCancel);

		pack();
		setLocationRelativeTo(parent);
		
		initListModel();
		list.repaint();
	}
	
	protected void initListModel() {
		ArrayList<PartsSet> partssets = new ArrayList<PartsSet>();
		for (PartsSet partsset : characterData.getPartsSets().values()) {
			if (!partsset.isPresetParts()) {
				partssets.add(partsset);
			}
		}
		Collections.sort(partssets, new Comparator<PartsSet>() {
			public int compare(PartsSet o1, PartsSet o2) {
				int ret = o1.getLocalizedName().compareTo(o2.getLocalizedName());
				if (ret == 0) {
					ret = o1.getPartsSetId().compareTo(o2.getPartsSetId());
				}
				if (ret == 0) {
					ret = o1.hashCode() - o2.hashCode();
				}
				return ret;
			}
		});
		list.setSelectedIndices(new int[0]);
		listModel.removeAllElements();
		for (PartsSet partsset : partssets) {
			listModel.addElement(partsset);
		}
	}
	
	protected void onDelete() {
		Map<String, PartsSet> partsSetMap = characterData.getPartsSets();
		for (Object value : list.getSelectedValues()) {
			PartsSet partsSet = (PartsSet) value;
			
			Iterator<Map.Entry<String, PartsSet>> ite = partsSetMap.entrySet().iterator();
			while (ite.hasNext()) {
				Map.Entry<String, PartsSet> entry = ite.next();
				PartsSet target = entry.getValue();
				if (target == partsSet) {
					dirty = true;
					ite.remove();
				}
			}
		}
		initListModel();
		list.repaint();
	}
	
	protected void onRename() {
		PartsSet partsSet = (PartsSet) list.getSelectedValue();
		if (partsSet != null) {
			Properties strings = LocalizedResourcePropertyLoader.getInstance()
					.getLocalizedProperties(STRINGS_RESOURCE);

			String localizedName = JOptionPane.showInputDialog(this, strings
					.getProperty("inputName"), partsSet.getLocalizedName());
			if (localizedName != null) {
				partsSet.setLocalizedName(localizedName);
				dirty = true;
				list.repaint();
			}
		}
	}
	
	protected void onClose() {
		dispose();
	}
	
	public boolean isModified() {
		return dirty;
	}
}
