/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.adventnet.sym.server.downloadmgr;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;

/**
 *
 * @author rajeshr-0486
 */
public class DCDownloadMgrProxyServer {

    static DownloadManager dwnManager = null;
    static int success = 0;
    static int fail = 0;

    public static void main(String args[]) {
        try {
            DCDownloadMgrProxyServer proxyserver = new DCDownloadMgrProxyServer();
            if (args.length == 0 || args.length % 2 == 1) {
                proxyserver.displayHelp();
                return;
            } else if (args.length == 2) {
                if (!args[0].equals("-c")) {
                    proxyserver.displayHelp();
                    return;
                }
            } else if (args.length == 4) {
                if (!args[2].equals("-f")) {
                    proxyserver.displayHelp();
                    return;
                }
            }
            dwnManager = DownloadManager.getInstance();
            Properties proxyProperties = proxyserver.loadProxySettings();
            if (args[1].equalsIgnoreCase("updatedb")) {
                if(proxyProperties != null) {
                    proxyserver.processUpdateDBRequest();
                }
	    } else if (args[1].equalsIgnoreCase("dwnpatch")) {
                String fileName = args[3];
                JSONObject requestObject = proxyserver.loadDownloadJson(fileName);
                if (requestObject != null) {
                    JSONArray jsonArray = requestObject.getJSONArray("data");
		    if(jsonArray.length() > 0)
		    {
                    System.out.println("Total Number of patches  is :: "+jsonArray.length());
		    File f = new File("downloadRemarks.txt");
		    if(f.exists() && f.isFile())
		    {
			    f.delete();
		    }
                    for (int i = 0; i < jsonArray.length(); i++) {
                        System.out.println("Counter  :: "+(i+1));
                        JSONObject request = jsonArray.getJSONObject(i);
                        proxyserver.processDownloadRequest(request);
                    }
		    if(fail > 0){
		    System.out.println("Download status : success == ::" + success +" and fail is:: "+fail);
		    System.out.println("Download Failed Details will be available in downloadRemarks.txt");
		    }

		    }else{
			    System.out.println("No Patches to download,proceed for deployment");
		    }
                }
            }else{
		    proxyserver.displayHelp();
	    }
        } catch (Exception exp) {
            exp.printStackTrace();
        }
    }

    public void displayHelp(){
        System.out.println("Command Usage : patchsync.bat -c updatedb");
        System.out.println("Command Usage : patchsync.bat -c dwnpatch -f downloadUrlJson.txt");
    }

    public Properties loadProxySettings() {
        Properties proxyProperties = null;
        FileInputStream pis = null;
        String proxyFileName = "downloadMgr.prop";
        try {
            if ((new File(proxyFileName).exists())) {
                pis = new FileInputStream(proxyFileName);
                proxyProperties = new Properties();
                proxyProperties.load(pis);

                dwnManager.setProxyConfiguration(proxyProperties);
            }
        } catch (Exception exp) {
            exp.printStackTrace();
        } finally {
            if (pis != null) {
                try {
                    pis.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
	return proxyProperties;
    }

    private JSONObject loadDownloadJson(String jsonFileName) throws Exception {
        JSONObject requestObject = null;
        try {
         //   String downloadUrl = "downloadUrl.txt";
            FileInputStream fis = null;
            byte[] content = null;
            try {
                if ((new File(jsonFileName).exists())) {
                    fis = new FileInputStream(jsonFileName);
                    content = new byte[fis.available()];
                    fis.read(content);
                    String jsonString = new String(content);
                    requestObject = new JSONObject(jsonString);
                }else{
			 System.out.println("Command Usage :Enter Valid File");
		}
             /*   if ((new File(downloadUrl).exists())) {
                    requestObject = loadDownloadUrl();
                }*/
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception exp) {
            exp.printStackTrace();
        }
        return requestObject;
    }

   /* private JSONObject loadDownloadUrl() throws Exception {

        JSONObject downloadJSON = new JSONObject();
        downloadJSON.accumulate("size", 0);
        downloadJSON.accumulate("type", "patch");
        JSONArray jsonArray = new JSONArray();
        FileReader fr = new FileReader("downloadUrl.txt");
        BufferedReader br = new BufferedReader(fr);
        String s;
        while ((s = br.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(s, ",");
            JSONObject patchObject = new JSONObject();
            int count = 0;
            while (st.hasMoreTokens()) {
                String data = st.nextToken();
                //System.out.println("data is ::"+data);
                switch (count) {
                    case 0:
                        patchObject.accumulate("PATCHID", data);
                        break;
                    case 1:
                        patchObject.accumulate("PATCHNAME", data);
                        break;
                    case 2:
                        patchObject.accumulate("PATH", data);
                        break;
                }
                count++;
            }
            System.out.println("patchObject is ::"+patchObject);
            jsonArray.put(patchObject);
        }
        fr.close();
        downloadJSON.accumulate("data", jsonArray);
        return downloadJSON;
    } */

    private JSONObject loadUpdateDBJson() throws Exception {
        JSONObject requestObject = null;
        try {
            String jsonFileName = "updateDBJson.txt";
            FileInputStream fis = null;
            byte[] content = null;
            try {
                if ((new File(jsonFileName).exists())) {
                    fis = new FileInputStream(jsonFileName);
                    content = new byte[fis.available()];
                    fis.read(content);
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            String jsonString = new String(content);
            requestObject = new JSONObject(jsonString);
        } catch (Exception exp) {
            exp.printStackTrace();
        }
        return requestObject;
    }

    public void processUpdateDBRequest() {
        try {
            String crsUrl = "http://patchdb.manageengine.com/";
           // String downloadUrl = crsUrl + "dccrs/crs-meta-data.conf";
            //String destinationFile = "updatedb" + File.separator + "dccrs" + File.separator + "crs-meta-data.conf";
            //DownloadStatus dwnStatus = dwnManager.downloadFile(downloadUrl, destinationFile);

         //   if (dwnStatus.getStatus() == 0) {
                String downloadUrl = crsUrl + "dc-crs/crs-meta-data.xml";
                String destinationFile = "updatedb" + File.separator + "dc-crs" + File.separator + "crs-meta-data.xml";
                DownloadStatus dwnStatus = dwnManager.downloadFile(downloadUrl, destinationFile);
                if (dwnStatus.getStatus() == 0) {
                    
                    File mainMetaFile = new File(destinationFile);
                    DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
                    domFactory.setNamespaceAware(true);
                    DocumentBuilder builder = domFactory.newDocumentBuilder();
                    Document doc = builder.parse(mainMetaFile);
                    XPath xpath = XPathFactory.newInstance().newXPath();
                    String expression = "//CRSMetaData"; //No I18N
                    XPathExpression expr = xpath.compile(expression);
                    Object result = expr.evaluate(doc, XPathConstants.NODESET);
                    NodeList nodeList = (NodeList) result;
                    for (int i = 0; i < nodeList.getLength(); i++) 
                    {
                        Node nodes = nodeList.item(i);
                        NamedNodeMap attributes = nodes.getAttributes();
                        String crsFilePath = ((Node) attributes.getNamedItem("crs_meta_data_file_path")).getNodeValue(); //No I18N
                        String crsFileName = ((Node) attributes.getNamedItem("crs_meta_data_file_name")).getNodeValue(); //No I18N

                        Boolean isReqFile = Boolean.TRUE;
                        ArrayList<String> unwantedFilesList = new ArrayList();
                        unwantedFilesList.add("software-details.xml");
                        unwantedFilesList.add("software-package.xml");
                        unwantedFilesList.add("script-repository.xml");

                        if(unwantedFilesList.contains(crsFileName)) {
                            isReqFile=Boolean.FALSE;
                        }

                        if(isReqFile)
                        {
                            //Definition file name
                            String defDetailsUrl = crsUrl +"/"+crsFilePath+"/"+crsFileName; //No I18N
                            String destinationDetailsFile = "updatedb" + File.separator+crsFilePath +File.separator+crsFileName;

                            dwnStatus = dwnManager.downloadFile(defDetailsUrl, destinationDetailsFile);
                            if (dwnStatus.getStatus() == 0) 
                            {
                                File file = new File(destinationDetailsFile);
                                DocumentBuilder defBuilder = domFactory.newDocumentBuilder();
                                Document defDoc = defBuilder.parse(file);
                                XPath defxpath = XPathFactory.newInstance().newXPath();
                                String defExpression = "//DefinitionMetaData"; //No I18N
                                XPathExpression defExpr = defxpath.compile(defExpression);
                                Object defResult = defExpr.evaluate(defDoc, XPathConstants.NODESET);
                                NodeList defNodeList = (NodeList) defResult;

                                for (int j = 0; j < defNodeList.getLength(); j++) {
                                    Node defNodes = defNodeList.item(j);
                                    NamedNodeMap defAttributes = defNodes.getAttributes();
                                    String dataFilePath = ((Node) defAttributes.getNamedItem("definition_file_path")).getNodeValue(); //No I18N
                                    String dataFileName = ((Node) defAttributes.getNamedItem("definition_file_name")).getNodeValue(); //No I18N
                                    String sqlDestinationFile = "updatedb" + File.separator + dataFilePath + File.separator + dataFileName;
                                    String sqlDownloadUrl = crsUrl + dataFilePath + "/" + dataFileName;
                                    File testFile = new File(sqlDestinationFile);
                                    if(testFile.exists()) {
                                        System.out.println("File already exists, download skipped for : " + sqlDestinationFile);
                                    } else {
                                        dwnManager.downloadFile(sqlDownloadUrl, sqlDestinationFile);
                                    }
                                }
                            }
                        }                                                
                    }
                    
                    
/*
                    
                    //patch-details
                    String patchDetailsUrl = crsUrl + "dccrs/definitiondata/patch-details.xml";
                    String destinationPatchDetailsFile = "updatedb" + File.separator + "dccrs" + File.separator + "definitiondata" + File.separator + "patch-details.xml";
                    if (isPgSql.equalsIgnoreCase("true")) {
                        patchDetailsUrl = crsUrl + "dccrs/definitiondata/patch-details-postgres.xml";
                        destinationPatchDetailsFile = "updatedb" + File.separator + "dccrs" + File.separator + "definitiondata" + File.separator + "patch-details-postgres.xml";
                    }
                    dwnStatus = dwnManager.downloadFile(patchDetailsUrl, destinationPatchDetailsFile);
                    if (dwnStatus.getStatus() == 0) {
                        File file = new File(destinationPatchDetailsFile);
                       // DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
                        //domFactory.setNamespaceAware(true);
                        DocumentBuilder builder = domFactory.newDocumentBuilder();
                        Document doc = builder.parse(file);
                        XPath xpath = XPathFactory.newInstance().newXPath();
                        String expression = "//DefinitionMetaData"; //No I18N
                        XPathExpression expr = xpath.compile(expression);
                        Object result = expr.evaluate(doc, XPathConstants.NODESET);
                        NodeList nodeList = (NodeList) result;
                        for (int i = 0; i < nodeList.getLength(); i++) {
                            Node nodes = nodeList.item(i);
                            NamedNodeMap attributes = nodes.getAttributes();
                            String dataFilePath = ((Node) attributes.getNamedItem("definition_file_path")).getNodeValue(); //No I18N
                            String dataFileName = ((Node) attributes.getNamedItem("definition_file_name")).getNodeValue(); //No I18N
                            String sqlDestinationFile = "updatedb" + File.separator + dataFilePath + File.separator + dataFileName;
                            String sqlDownloadUrl = crsUrl + dataFilePath + "/" + dataFileName;
                            dwnManager.downloadFile(sqlDownloadUrl, sqlDestinationFile);
                        }
                    }

                    //patch-scan
                    String patchScanDetailsUrl = crsUrl + "dccrs/definitiondata/patch-scan-details.xml";
                    String destinationPatchScanDetailsFile = "updatedb" + File.separator + "dccrs" + File.separator + "definitiondata" + File.separator + "patch-scan-details.xml";
                    dwnStatus = dwnManager.downloadFile(patchScanDetailsUrl, destinationPatchScanDetailsFile);
                    if (dwnStatus.getStatus() == 0) {
                        File file = new File(destinationPatchScanDetailsFile);
                        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
                        domFactory.setNamespaceAware(true);
                        DocumentBuilder builder = domFactory.newDocumentBuilder();
                        Document doc = builder.parse(file);
                        XPath xpath = XPathFactory.newInstance().newXPath();
                        String expression = "//DefinitionMetaData"; //No I18N
                        XPathExpression expr = xpath.compile(expression);
                        Object result = expr.evaluate(doc, XPathConstants.NODESET);
                        NodeList nodeList = (NodeList) result;
                        for (int i = 0; i < nodeList.getLength(); i++) {
                            Node nodes = nodeList.item(i);
                            NamedNodeMap attributes = nodes.getAttributes();
                            String dataFilePath = ((Node) attributes.getNamedItem("definition_file_path")).getNodeValue(); //No I18N
                            String dataFileName = ((Node) attributes.getNamedItem("definition_file_name")).getNodeValue(); //No I18N
                            String sqlDestinationFile = "updatedb" + File.separator + dataFilePath + File.separator + dataFileName;
                            String sqlDownloadUrl = crsUrl + dataFilePath + "/" + dataFileName;
                            dwnManager.downloadFile(sqlDownloadUrl, sqlDestinationFile);
                        }
                    }
                    //mac-patch-scan
                    String macPatchScanDetailsUrl = crsUrl + "dccrs/definitiondata/mac-patch-scan-details.xml";
                    String macPatchScanDetailsFile = "updatedb" + File.separator + "dccrs" + File.separator + "definitiondata" + File.separator + "mac-patch-scan-details.xml";
                    dwnStatus = dwnManager.downloadFile(macPatchScanDetailsUrl, macPatchScanDetailsFile);
                    if (dwnStatus.getStatus() == 0) {
                        File file = new File(macPatchScanDetailsFile);
                        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
                        domFactory.setNamespaceAware(true);
                        DocumentBuilder builder = domFactory.newDocumentBuilder();
                        Document doc = builder.parse(file);
                        XPath xpath = XPathFactory.newInstance().newXPath();
                        String expression = "//DefinitionMetaData"; //No I18N
                        XPathExpression expr = xpath.compile(expression);
                        Object result = expr.evaluate(doc, XPathConstants.NODESET);
                        NodeList nodeList = (NodeList) result;
                        for (int i = 0; i < nodeList.getLength(); i++) {
                            Node nodes = nodeList.item(i);
                            NamedNodeMap attributes = nodes.getAttributes();
                            String dataFilePath = ((Node) attributes.getNamedItem("definition_file_path")).getNodeValue(); //No I18N
                            String dataFileName = ((Node) attributes.getNamedItem("definition_file_name")).getNodeValue(); //No I18N
                            String sqlDestinationFile = "updatedb" + File.separator + dataFilePath + File.separator + dataFileName;
                            String sqlDownloadUrl = crsUrl + dataFilePath + "/" + dataFileName;
                            dwnManager.downloadFile(sqlDownloadUrl, sqlDestinationFile);
                        }
                    }
                }
*/
            }
        } catch (Exception exp) {
            exp.printStackTrace();
        }
    }

    public void processDownloadRequest(JSONObject requestObject) {
        try {
            String downloadUrl = requestObject.getString("PATH");
            String patchID = requestObject.getString("PATCHID");
            String fileName = requestObject.getString("PATCHNAME");
            String destinationFile = "store" + File.separator + patchID + "-" + fileName;
            DownloadStatus dwnStatus = dwnManager.downloadFile(downloadUrl, destinationFile);
	    int statusCode = dwnStatus.getStatus();
	    if(statusCode == 0)
	    {
		    success = success +1;
	    }
	    else{
		    fail=fail+1;
		    String content = patchID + "\t"+fileName + "\t" +downloadUrl;
		    BufferedWriter bw = new BufferedWriter(new FileWriter(new File("downloadRemarks.txt"), true));
                        bw.write(content);
                        bw.newLine();
                        bw.close();

	    }
            System.out.println("Download Status : " + dwnStatus.dwnloadstatus);
            System.out.println("Download Patch Name : " + fileName);
        } catch (Exception exp) {
            exp.printStackTrace();
        }
    }

    public String extractFiles(String inputFileName) throws Exception {
        String outputFileName = null;
        String outputDir = "temp_extract";
        outputFileName = inputFileName.replaceAll(".exe", ".msp");
        String cmd = "7z e " + inputFileName + "-aoa -o" + outputDir + " *.msp -r";
        execute(new String[]{"cmd.exe", "/c", cmd});
        File f = new File(outputDir);
        File[] files = f.listFiles();
        if ( files.length > 0 ){
            for ( int i = 0 ; i < files.length; i++ ){
                File f1 = new File(outputFileName);
                files[i].renameTo(f1);
            }
        } else {
            System.out.println("Not processed files : " + inputFileName);
        }
        return outputFileName;
    }

    public static String execute(String[] command) throws Exception {
        final StringBuffer strBuff = new StringBuffer();
        final String cmd[] = command;
        try {
            InputStream consoleInput = null;
            InputStream consoleError = null;
            String readstr = "";
            final Process process = Runtime.getRuntime().exec(cmd);
            consoleInput = process.getInputStream();
            consoleError = process.getErrorStream();
            final BufferedReader readinput = new BufferedReader(new InputStreamReader(consoleInput));
            BufferedReader readerr = new BufferedReader(new InputStreamReader(consoleError));

            Thread th = new Thread(new Runnable() {

                public void run() {
                    String readStr;
                    try {
                        while ((readStr = readinput.readLine()) != null) {
                            strBuff.append(readStr);
                            strBuff.append(System.getProperty("line.separator"));
                            try {
                                if (process.exitValue() == 0) {
                                    return;
                                }
                            } catch (IllegalThreadStateException ill) {
                                //throw new Exception(ill.getMessage());
                            }
                        }
                    } catch (IOException ioex) {
                        ioex.printStackTrace();
                        //throw new Exception(ioex.getMessage());
                    }
                }
            }, "ExecInputRead");
            th.start();
            try {
                while ((readstr = readerr.readLine()) != null) {
                    System.out.println("Error while executing command----> " + readstr);
                    throw new Exception("Error while executing command " + readstr);
                }
            } catch (IOException io) {
                System.out.println("Input error" + io);
                throw new Exception(io.getMessage());
            }

            process.waitFor();
            th.join();
            return strBuff.toString();

        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        }
    }
}


