/*
    AVR8 Burn-O-Mat
 
    Copyright (C) 2007  Torsten Brischalle

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/
 */

package de.lazyzero.kkMulticopterFlashTool.utils;

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

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.DOMStringList;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import avr8_burn_o_mat.XmlUtil;
import de.lazyzero.kkMulticopterFlashTool.KKMulticopterFlashTool;


public class XmlReaderFirmwares {
    
    private Vector <Firmware> firmwares = new Vector <Firmware>();
    private double actualVersion;
	private String firmwareRepositoryURL;
	private String firmwareRepositoryMirrorURL;
	private String url;
    
    /** Creates a new instance of FuseReader */
    public XmlReaderFirmwares() {
    }
    
    public XmlReaderFirmwares(URL firmwareRepositoryURL, URL mirrorURL) {
    	this.firmwareRepositoryURL = firmwareRepositoryURL.toString();
    	this.firmwareRepositoryMirrorURL = mirrorURL.toString();
    	if (KKMulticopterFlashTool.isOfflineMode()){
    		url = KKMulticopterFlashTool.getTempFolder()+"firmwares.xml";
    		try {
				readXmlFile(url);
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, _("error.offlineRepository"));
				e.printStackTrace();
			}
    	} else {
    		try {
    			System.out.println("repository URL: " + firmwareRepositoryURL.toString());
    			url = this.firmwareRepositoryURL;
    			readXmlFile(url);
    			downloadFirmwareDescription(new URL(url));
    		} catch (Exception e) {
    			try {
    				System.out.println("repository mirror URL: " + firmwareRepositoryMirrorURL.toString());
    				url = this.firmwareRepositoryMirrorURL;
    				readXmlFile(url);
    				downloadFirmwareDescription(new URL(url));
    			} catch (Exception e2) {
    				JOptionPane.showMessageDialog(null, _("error.repository"));
    				e.printStackTrace();
    			}
    		}
    	}
	}
    
    
	public Vector<Firmware> getFirmwares() {
		return firmwares;
	}


	
	public Vector<Firmware> getFirmwares(String controllerName) {
		System.out.println("Adding firmwares for controller: " + controllerName);
		if(controllerName.endsWith("p")){
			controllerName=controllerName.replace("p", "");
			System.out.println(controllerName);
		} else if (controllerName.endsWith("pa")){
			controllerName=controllerName.replace("pa", "");
			System.out.println(controllerName);
		}
		Vector <Firmware> fw = new Vector<Firmware>();
		Enumeration<Firmware> en = firmwares.elements();
		while (en.hasMoreElements()) {
			Firmware firmware = (Firmware) en.nextElement();
			if (firmware.getController().contains(controllerName)){
				fw.add(firmware);
				System.out.println("add firmware to drop down list " + firmware);
			}
		}
		
		Collections.sort(fw, new Comparator<Firmware>() {

			@Override
			public int compare(Firmware o1, Firmware o2) {
				// TODO Auto-generated method stub
				return o2.toString2().compareTo(o1.toString2());
			}
		});

		
		return fw;
	}
    
    public void readXmlFile(String uri) throws Exception {
    	//test the connection first
    	try {
    		URL url = new URL(uri);
    		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    		conn.setReadTimeout(5000);
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		
        DocumentBuilderFactory factory  = DocumentBuilderFactory.newInstance();
        DocumentBuilder        builder  = factory.newDocumentBuilder();
        Document               document = builder.parse(uri);
        
        Node node = document.getDocumentElement().getFirstChild();
        firmwares.removeAllElements();
        
        while (node != null) {
            if (node.getNodeName().equals("firmware")) {
                readFirmware(node);
            }
            if (node.getNodeName().equals("version")) {
                readVersion(node);
            }
            
            node = node.getNextSibling();
        }
        
    }
    
    private void readVersion(Node node) {
		actualVersion = Double.parseDouble(XmlUtil.getAttr(node, "name"));
	}

	private void readFirmware(Node node) throws Exception {
        
        Node nodeFirmware = node.getFirstChild();
        String author = new String();
        String controller = new String();
        String md5 = new String();
        URL url = null;
        URL zipurl = null;
        String name = XmlUtil.getAttr(node, "name");
        String version = XmlUtil.getAttr(node, "value");
        
        
        
        while (nodeFirmware != null) {
            
        	if (nodeFirmware.getNodeName().equals("author")) {
        		author = XmlUtil.getAttr(nodeFirmware, "name");
            }
        	if (nodeFirmware.getNodeName().equals("controller")) {
        		controller = XmlUtil.getAttr(nodeFirmware, "name");
            }
        	if (nodeFirmware.getNodeName().equals("file")) {
        		url = new URL(XmlUtil.getAttr(nodeFirmware, "url"));
            }
        	try {
        		if (nodeFirmware.getNodeName().equals("zipfile")) {
        			zipurl = new URL(XmlUtil.getAttr(nodeFirmware, "url"));
        		}
			} catch (Exception e) {
				zipurl = null;
			}
        	if (nodeFirmware.getNodeName().equals("md5")) {
        		md5 = new String(XmlUtil.getAttr(nodeFirmware, "value"));
            }
            
            nodeFirmware = nodeFirmware.getNextSibling();
        }
        
        Firmware firmware = new Firmware(url);
        firmware.setName(name);
        firmware.setVersion(version);
        firmware.setController(controller);
        firmware.setAuthor(author);
        firmware.setZipURL(zipurl);
        firmware.setMD5(md5);
        
       //firmware.getFile();
        
        firmwares.add(firmware);
    }
	
	private File downloadFirmwareDescription(URL url){
		String filename = null;
		String tmpdir = null;
		
		String urlPath = url.getPath();
		filename = urlPath.substring(urlPath.lastIndexOf("/")+1);
		System.out.println("Download firmware description file: "+filename);
		
        tmpdir = KKMulticopterFlashTool.getTempFolder();
        filename = tmpdir + filename;
        	
		File tmpFile = new File(filename);
		if ((new File(tmpdir)).mkdir()) System.out.println("tmpdir created");
		
		
    		try {
    			
    			BufferedInputStream in = new BufferedInputStream(url.openStream());
    			FileOutputStream fos = new FileOutputStream(tmpFile);
    			BufferedOutputStream bout = new BufferedOutputStream(fos,1024);
    			byte[] data = new byte[1024];
    			int x=0;
    			while((x=in.read(data,0,1024))>=0) {
    				bout.write(data,0,x);
    			}
    			bout.close();
    			in.close();
    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
		

		System.out.println("Download finished: " + filename);
		return tmpFile;
	}
	
	public static void main(String[] args) {
		XmlReaderFirmwares f = new XmlReaderFirmwares();
		try {
			f.readXmlFile("./firmwares.xml");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public String getURL() {
		return this.url;
	}

	/**
	 * @return the actualVersion
	 */
	public double getActualVersion() {
		return actualVersion;
	}

	
	
    
}
