import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;

public class PatternEditorJDialog extends JDialog implements ActionListener, FocusListener {
	private static final long serialVersionUID = 1L;
	private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14);
	private static final String[] fieldsNames = new String[] {
			"Low time : ", //0
			"Rise time : ", //1
			"High time : ", //2
			"Fall time : ", //3
			"Low time : ", //4
			"Repeat : ", //5
			"Begin time : ", //6
			"Volume : ", //7
			"Path : ", //8
			"Duration : ", //9
			"Pattern time : ", //10
			"Total time : " //11
	};
	private void generateComponents() {
		fields = new Component[fieldsNames.length];
		
		// 7 textfields
		for(int i=0; i<7; i++) {
			fields[i] = new JTextField(10);
			fields[i].addFocusListener(this);
		}
		
		// 1 slider
		fields[7] = new JSlider(0, 10, 8);
		((JSlider) fields[7]).setMajorTickSpacing(2);
		((JSlider) fields[7]).setMinorTickSpacing(1);
		((JSlider) fields[7]).setPaintTicks(true);
		
		// 1 combobox
		fields[8] = new JComboBox<String>(MusicPath.pathNames);
		
		
		// 1 textfields
		fields[9] = new JTextField(10);
		fields[9].addFocusListener(this);
		
		// 2 textfields disabled
		for(int i=10; i<12; i++) {
			fields[i] = new JTextField(10);
			fields[i].setEnabled(false);
			fields[i].addFocusListener(this);
			fields[i].setForeground(Color.DARK_GRAY);
		}
	}
	
	private Component[] fields;
	private JButton ok;
	private JButton cancel;
	private Music music = null;
	
	public PatternEditorJDialog(Frame parent) { this(parent, null); }
	public PatternEditorJDialog(Frame parent, Music musicPrev) {
		super(parent, "Pattern editor", true);
		generateComponents();
		
		// main panel
		
		JPanel mainPanel = new JPanel(new BorderLayout());
		getContentPane().add(mainPanel);
		
		// title
		
		JPanel titlePanel = new JPanel(new FlowLayout());
		JLabel title = new JLabel("Pattern parameters : ");
		title.setFont(titleFont);
		titlePanel.add(title);
		mainPanel.add(titlePanel, BorderLayout.NORTH);
		
		// center panel
		JPanel centerPanel = new JPanel();
		centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.LINE_AXIS));
		mainPanel.add(centerPanel, BorderLayout.CENTER);
		//padding
		centerPanel.add(Box.createRigidArea(new Dimension(5, 0)));

		// labels panel
		JPanel labelsPanel = new JPanel();
		labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.PAGE_AXIS));
		centerPanel.add(labelsPanel);
		
		// fields panel
		JPanel fieldsPanel = new JPanel();
		fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.PAGE_AXIS));
		centerPanel.add(fieldsPanel);
		//padding
		centerPanel.add(Box.createRigidArea(new Dimension(5, 0)));
		
		JLabel[] fieldsLabels = new JLabel[fieldsNames.length];
		for(int i=0; i<fields.length; i++) {
			fieldsPanel.add(fields[i]);
			
			fieldsLabels[i] = new JLabel(fieldsNames[i]);
			fieldsLabels[i].setAlignmentX(Component.RIGHT_ALIGNMENT);
			fieldsLabels[i].setMaximumSize(new Dimension(fieldsLabels[i].getPreferredSize().width, fields[i].getPreferredSize().height));
			labelsPanel.add(fieldsLabels[i]);
		}
		
		// buttons
		
		JPanel buttonsPanel = new JPanel(new FlowLayout());
		mainPanel.add(buttonsPanel, BorderLayout.SOUTH);

		ok = new JButton("Ok");
		ok.addActionListener(this);
		buttonsPanel.add(ok);
		
		cancel = new JButton("Cancel");
		cancel.addActionListener(this);
		buttonsPanel.add(cancel);
		
		setResizable(false);
		pack();
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

		
		// load prev music
		music = musicPrev;
		if(musicPrev != null)
			updateFeildsToMusic();
		
		// format and compute disabled fields
		updateFields();
	}
	
	private void updateFeildsToMusic() {
		int[] pattern = music.getMusicPattern().getPattern();
		((JTextField) fields[0]).setText(String.valueOf(pattern[0]));
		((JTextField) fields[1]).setText(String.valueOf(pattern[1]));
		((JTextField) fields[2]).setText(String.valueOf(pattern[2]));
		((JTextField) fields[3]).setText(String.valueOf(pattern[3]));
		((JTextField) fields[4]).setText(String.valueOf(pattern[4]));

		((JTextField) fields[5]).setText(String.valueOf(music.getMusicPattern().getRepeat()));
		((JTextField) fields[6]).setText(String.valueOf(music.getMusicPattern().getBegin()));
		
		((JSlider) fields[7]).setValue((int) (music.getVolume() * 10d));

		MusicPath path = music.getMusicPath();
		((JComboBox<?>) fields[8]).setSelectedIndex(path.getAnimation());
		
		((JTextField) fields[9]).setText(String.valueOf(path.getEffectDuration()));
	}
	
	public Music showDialog() {
		setVisible(true);
		return music;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == ok) {
			updateFields();
			
			int lowTime = (int) Util.textToTick(((JTextField) fields[0]).getText());
			int raiseTime = (int) Util.textToTick(((JTextField) fields[1]).getText());
			int highTime = (int) Util.textToTick(((JTextField) fields[2]).getText());
			int fallTime = (int) Util.textToTick(((JTextField) fields[3]).getText());
			int pauseTime = (int) Util.textToTick(((JTextField) fields[4]).getText());
			int repeats = Integer.parseInt(((JTextField) fields[5]).getText());
			long beginTime = Util.textToTick(((JTextField) fields[6]).getText());
			
			int animationId = ((JComboBox<?>) fields[8]).getSelectedIndex();
			int effectDuration = (int) Util.textToTick(((JTextField) fields[9]).getText());
			
			MusicPattern musicPattern = new MusicPattern(new int[] {lowTime, raiseTime, highTime, fallTime, pauseTime}, repeats, beginTime);
			MusicPath musicPath = new MusicPath(animationId, effectDuration);
			double volume = (double) ((JSlider) fields[7]).getValue() / (double) ((JSlider) fields[7]).getMaximum();
			
			//invalid params
			if((lowTime == 0 && raiseTime == 0 && highTime == 0 && fallTime == 0 && pauseTime == 0)
					|| (repeats <= 0)
					|| (beginTime < 0)
					|| (effectDuration < 0)) {
				music = null;
				dispose();
				return;
			}
			
			music = new Music(musicPattern, musicPath, volume);
			
			dispose();
		} else if(e.getSource() == cancel) {
			music = null;
			dispose();
		}
	}
	
	public void updateFields() {
		// format textfields
		for(int i=0; i<fields.length; i++) {
			if(fields[i] instanceof JTextField && i != 5)
				((JTextField) fields[i]).setText(Util.formatTime(((JTextField) fields[i]).getText()));
			else if(i == 5) {
				try {
					int n = Integer.parseInt(((JTextField) fields[i]).getText());
					if(n < 1)
						((JTextField) fields[i]).setText("1");
				}catch (NumberFormatException e) {
					((JTextField) fields[i]).setText("1");
				}
			}
		}

		// compute patter time and total time
		long lowTime = Util.textToTick(((JTextField) fields[0]).getText());
		long raiseTime = Util.textToTick(((JTextField) fields[1]).getText());
		long highTime = Util.textToTick(((JTextField) fields[2]).getText());
		long fallTime = Util.textToTick(((JTextField) fields[3]).getText());
		long pauseTime = Util.textToTick(((JTextField) fields[4]).getText());
		int repeats = Integer.parseInt(((JTextField) fields[5]).getText());

		long patterTime = lowTime + raiseTime + highTime + fallTime + pauseTime;
		((JTextField) fields[10]).setText(Util.tickToText(patterTime));
		long totalTime = patterTime * repeats;
		((JTextField) fields[11]).setText(Util.tickToText(totalTime));
	}

	@Override
	public void focusGained(FocusEvent e) {}

	@Override
	public void focusLost(FocusEvent e) {
		updateFields();
	}
}
