package de.lazyzero.kkMulticopterFlashTool.gui;

import static lu.tudor.santec.i18n.Translatrix._;

import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URL;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileFilter;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import de.lazyzero.kkMulticopterFlashTool.KKMulticopterFlashTool;
import de.lazyzero.kkMulticopterFlashTool.gui.widgets.FirmwareListCellRenderer;
import de.lazyzero.kkMulticopterFlashTool.utils.Firmware;
import de.lazyzero.kkMulticopterFlashTool.utils.Icons;
import de.lazyzero.kkMulticopterFlashTool.utils.XmlReaderFirmwares;

public class FirmwarePanel extends  JPanel implements ActionListener, PropertyChangeListener{

	private static final long serialVersionUID = 1L;
	private XmlReaderFirmwares firmwareLoader;
	private KKMulticopterFlashTool parent;
	private JComboBox firmwareCombobox;
	private JComboBox firmwareCategoryCombobox;
	private JButton reload;
	private JButton flash; 
	
	private Vector<Firmware> firmwares = new Vector<Firmware>();
	private TitledBorder firmwareBorder;
	private CellConstraints cc;
	private JLabel firmwareLabel;
	private JTextField firmwareFileField;
	private JButton flashFile;
	private JLabel firmwareFileLabel;
	private JButton load;
	private JFileChooser fc;
	private FileFilter ffilter;
	private File firmwareFile;
	private Vector<String> categories = new Vector<String>();
	private JButton info;
	private Logger logger = KKMulticopterFlashTool.getLogger();
	private int item;

	public FirmwarePanel(KKMulticopterFlashTool parent,
			XmlReaderFirmwares firmwareLoader) {
		this.parent = parent;
		this.firmwareLoader = firmwareLoader;
		init();
		
		this.addPropertyChangeListener(this);
	}

	private void init() {
		fc = new JFileChooser(parent.getSettings().getProperty("last.dir","%HOME%"));
		fc.setFileSelectionMode(JFileChooser.FILES_ONLY);

		ffilter = new FileFilter() {
			
			@Override
			public String getDescription() {
				return "Hex-File (.hex)";
			}
		
			@Override
			public boolean accept(File f) {
				return f.isDirectory() || f.getAbsoluteFile().toString().toLowerCase().endsWith(".hex");
			}
		};
		
		fc.setFileFilter(ffilter);
		
		//create the CellContraints
		cc  = new CellConstraints();
		
		// create the Layout for Panel this
		String panelColumns = "pref,3dlu,fill:pref:grow,3dlu,pref,3dlu,pref";
		String panelRows = "pref,3dlu,pref,3dlu,pref:grow,3dlu,top:pref:grow";
		FormLayout panelLayout = new FormLayout(panelColumns, panelRows);
		this.setLayout(panelLayout);
		
		JLabel helpLabel = new JLabel(_("firmware.help"));
		
		firmwareLabel = new JLabel(_("firmware"));
		firmwareLabel.setToolTipText(_("firmware.FirmwareCombobox.tip"));
		
		firmwareFileLabel = new JLabel(_("firmware.file"));
		firmwareFileLabel.setToolTipText(_("firmware.load.tip"));
		
		this.setBorder(new TitledBorder(_("firmware.settings")));
		

		this.categories.add(_("firmware.allCategories"));
		this.categories.addAll(Firmware.getCategories(firmwareLoader.getFirmwares()));
		firmwareCategoryCombobox = new JComboBox(categories);
		firmwareCategoryCombobox.setSelectedIndex(0);
		firmwareCategoryCombobox.addActionListener(this);
		firmwareCategoryCombobox.setToolTipText(_("firmware.CategoryCombobox.tip"));
		
		
		firmwareFileField = new JTextField();
		firmwareFileField.setToolTipText(_("firmware.load.tip"));
		
		
		firmwareCombobox = new JComboBox();
		firmwareCombobox.setModel(new DefaultComboBoxModel());
		firmwareCombobox.setBorder(firmwareBorder);
		firmwareCombobox.setToolTipText(_("firmware.FirmwareCombobox.tip"));
		firmwareCombobox.addActionListener(this);
		firmwareCombobox.setRenderer(new FirmwareListCellRenderer());
		
		reload = new JButton(Icons.getIcon16(Icons.RELOAD));
		reload.addActionListener(this);
		reload.setToolTipText(_("reload.tip"));
		
		
		flash = new JButton(Icons.getIcon16(Icons.RUN));
		flash.addActionListener(this);
		flash.setEnabled(false);
		flash.setToolTipText(_("firmware.flash.tip"));
		
		
		info = new JButton(Icons.getIcon16(Icons.INFO));
		info.addActionListener(this);
		info.setEnabled(false);
		info.setToolTipText(_("firmware.info.tip"));
		
		
		load = new JButton(Icons.getIcon16(Icons.LOAD));
		load.addActionListener(this);
		load.setToolTipText(_("firmware.load.tip"));
		
		
		flashFile = new JButton(Icons.getIcon16(Icons.RUN));
		flashFile.addActionListener(this);
		flashFile.setEnabled(false);
		flashFile.setToolTipText(_("firmware.flashFile.tip"));
		
		
		this.add(helpLabel, cc.xyw(1, 1, 7));
		this.add(firmwareFileLabel, cc.xy(1, 3));
		this.add(firmwareFileField, cc.xy(3, 3));
		this.add(load, cc.xy(5,3));
		this.add(flashFile, cc.xy(7,3));
		this.add(new JSeparator(), cc.xyw(1, 4, 7));
		this.add(firmwareCategoryCombobox, cc.xy(3,5));
		this.add(firmwareLabel, cc.xy(1, 7));
		this.add(firmwareCombobox, cc.xy(3,7));
		this.add(reload, cc.xy(5,5));
		this.add(flash, cc.xy(7,7));
		this.add(info, cc.xy(5,7));
	}

	@Override
	public void actionPerformed(ActionEvent action) {
		if (action.getSource().equals(firmwareCategoryCombobox)){
			item = firmwareCategoryCombobox.getSelectedIndex();
			parent.clearText();
			updateComboboxes();
		} else if (action.getSource().equals(reload)){
			parent.clearText();
			parent.println(_("messages.reloadList"));
			
			try {
				firmwareLoader.reloadXmlFile(new URL(firmwareLoader.getURL()));
			} catch (Exception e) {
				parent.println(_("messages.reloadList.error"));
				e.printStackTrace();
				return;
			}
			updateComboboxes();
			
		}else if (action.getSource().equals(firmwareCombobox)) {
			try {
				if (!KKMulticopterFlashTool.isOfflineMode() && ((Firmware)firmwareCombobox.getSelectedItem()).hasCommentURL()){
					info.setEnabled(true);
				} else {
					info.setEnabled(false);
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		} else if (action.getSource().equals(flash)){
			parent.clearText();
			parent.println(_("messages.flashRepository"));
//			firmwareFile = ((Firmware)firmwareCombobox.getSelectedItem()).getFile(); 
			parent.setFirmware(((Firmware)firmwareCombobox.getSelectedItem()));
			parent.flashAVR();
		} else if (action.getSource().equals(load)){

			if (action.getSource().equals(load)) {
				int returnVal = fc.showOpenDialog(this);

				if (returnVal == JFileChooser.APPROVE_OPTION) {
					firmwareFile = fc.getSelectedFile();
					// This is where a real application would open the file.
					firmwareFileField.setText(firmwareFile.getName());
					parent.setFirmware(new Firmware(firmwareFile));
					parent.clearText();
					parent.println(_("messages.loadFile"));
					flashFile.setEnabled(true);
				} else {
					firmwareFileField.setText("");
					parent.clearText();
					parent.println(_("messages.nothingLoad"));
					flashFile.setEnabled(false);
				}
			}
			
		} else if (action.getSource().equals(flashFile)){
			parent.clearText();
			parent.println(_("messages.flashFile"));
			parent.flashAVR();
		} else if (action.getSource().equals(info)) {
			if(Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)){
				try {
					Desktop.getDesktop().browse(((Firmware)firmwareCombobox.getSelectedItem()).getCommentURL().toURI());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					logger.log(Level.WARNING, e.getMessage());
				} 
			} else {
				JOptionPane.showMessageDialog(null, _("error.commentURL") + ((Firmware)firmwareCombobox.getSelectedItem()).getCommentURL().toExternalForm());
			}
		}
		
	}

	private void updateComboboxes() {
		String controllerName = parent.getController().getCaption();

		firmwares = firmwareLoader.getFirmwares(controllerName);
		
		firmwareCategoryCombobox.removeAllItems();
		this.categories = new Vector<String>();
		this.categories.add(_("firmware.allCategories"));
		this.categories.addAll(Firmware.getCategories(firmwares));
		for (int i = 0; i < categories.size(); i++) {
			firmwareCategoryCombobox.addItem(categories.get(i));
		}
		if (firmwareCategoryCombobox.getItemCount()>0){
			firmwareCategoryCombobox.setSelectedIndex(0);
		} 
		if (item > 0) {
			firmwareCategoryCombobox.setSelectedIndex(item);
		}
		
		if (KKMulticopterFlashTool.isOfflineMode()){
			firmwares = Firmware.getOfflineAvailableFirmwares(firmwares);
		}
		
		if (!this.firmwareCategoryCombobox.getSelectedItem().equals(_("firmware.allCategories"))) {
			firmwares = Firmware.filter((String)this.firmwareCategoryCombobox.getSelectedItem(), firmwares);
			}
		
		parent.println(_("messages.reloadList.done"));
		firmwareCombobox.removeAllItems();
		System.out.println("firmwares loaded: " + firmwares.size());
		for (int i = 0; i < firmwares.size(); i++) {
			firmwareCombobox.addItem(firmwares.get(i));
		}
		if (firmwareCombobox.getItemCount()>0){
			firmwareCombobox.setSelectedIndex(0);
			flash.setEnabled(true);
		} else {
			flash.setEnabled(false);
		}
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (evt.getPropertyName().equals(ControllerPanel.CONTROLLER_CHANGED)) {
			parent.clearText();
			updateComboboxes();
		}
	}

}
