/**************************************************************************************************
* Copyright (c) 1997-2016, 2018 Flexera. All Rights Reserved.
**************************************************************************************************/
package alerter;

import java.io.StringReader;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Aleter is a web client of the web services offered by the License Manager.
 * It periodically checks for any new alerts and sends out notification email.
 */
public class Alerter {
    /** Interval between checks for new alerts */
    private static final int DEFAULT_POLL_INTERVAL = 5*60; // 5 minutes

    /** 
     * The Alerter main program,
     *
     * @param args Command line arguments
     */
    public static void main(String[] args) {
        Alerter alerter = new Alerter();
        alerter.processArgs(args);
        alerter.run();
    }
    
    /** Initialize the Alerter */
    private Alerter() {
        // create XML parser
        try {
            docBuilder = 
                DocumentBuilderFactory.newInstance().newDocumentBuilder();
        }
        catch (Exception e) {
            System.out.println("Couldn't create document builder: "+e);
            System.exit(1);
        }
    }

    /** The main loop for the Alerter service. */
    private void run() {
        while (true) {
            // get the current alerts, if nothing comes back there was an error
            String xmlAlerts = connection.getAlerts(lastId);
            if (xmlAlerts.length() == 0)
                return;
            
            processAlerts(xmlAlerts);
            
            // wait before checking again
            try {
                Thread.sleep(pollInterval*1000);
            }
            catch(java.lang.InterruptedException e) {}
        }
    }
    
    /**
     * Process the command line arguments.
     *
     * @param args Command line arguments
     */
    private void processArgs(String[] args) {
        // fill in some defaults
        String host = "localhost";
        int port = 8090;
        String user = "alerter";
        String password = "alerter";
        String persistFile = "../../conf/alerter_state.properties";
        String smtpServer = "mail";
        int smtpPort = 25;
        String smtpUser = null;
        String smtpPassword = null;
        String smtpFrom = "LicenseManagerAlerter";
        String smtpTo = "LicenseManagerAlerts";
        
        // process the command line options
        String HOST_OPTION = "-host";
        String INTERVAL_OPTION = "-interval";
        String PASSWORD_OPTION = "-password";
        String PERSIST_OPTION = "-persist";
        String PORT_OPTION = "-port";
        String SMTP_FROM_OPTION = "-fromAddress";
        String SMTP_PASSWORD_OPTION = "-smtpPassword";
        String SMTP_PORT_OPTION = "-smtpPort";
        String SMTP_SERVER_OPTION = "-smtpServer";
        String SMTP_TO_OPTION = "-toAddress";
        String SMTP_USER_OPTION = "-smtpUser";
        String USER_OPTION = "-user";

        for (int i = 0; i < args.length; i++) {
            String option = args[i++];
            if (i >= args.length)
                usage();
            String value = args[i];
            if (option.equals(HOST_OPTION))
                host = value;
            else if (option.equals(PORT_OPTION))
                port = Integer.valueOf(value).intValue();
            else if (option.equals(USER_OPTION))
                user = value;
            else if (option.equals(PASSWORD_OPTION))
                password = value;
            else if (option.equals(PERSIST_OPTION))
                persistFile = value;
            else if (option.equals(SMTP_SERVER_OPTION))
                smtpServer = value;
            else if (option.equals(SMTP_PORT_OPTION))
                smtpPort = Integer.valueOf(value).intValue();
            else if (option.equals(SMTP_USER_OPTION))
                smtpUser = value;
            else if (option.equals(SMTP_PASSWORD_OPTION))
                smtpPassword = value;
            else if (option.equals(SMTP_FROM_OPTION))
                smtpFrom = value;
            else if (option.equals(SMTP_TO_OPTION))
                smtpTo = value;
            else if (option.equals(INTERVAL_OPTION))
                pollInterval = Integer.valueOf(value).intValue();
            else
                usage();
        }
        
        // connect to the web service
        connection = new Connection(host, port, user, password);
        
        // create email sender
        email = new Email(smtpServer, smtpPort, smtpUser, smtpPassword,
                          smtpFrom, smtpTo);
        
        // setup access to last alert persistence
        persist = new Persist(persistFile);
        lastId = persist.getLastId();
    }

    /**
     * Process the alerts.
     *
     * @param xmlAlerts The XML respresenting the alerts
     */
    private void processAlerts(String xmlAlerts) {
        Document doc;
        try {
            doc = docBuilder.parse(
                      new InputSource(new StringReader(xmlAlerts)));
        }
        catch (Exception e) {
            System.out.println("Problem parsing alert: "+e);
            return;
        }
        
        // extract info from the <fnplm:alert> nodes
        NodeList alertNodes = doc.getElementsByTagName("fnplm:alert");
        String highestId = lastId;
        for (int i = 0; i < alertNodes.getLength(); i++) {
            Element elem = (Element)alertNodes.item(i);
            String id = elem.getAttribute("id");
            if (id.compareTo(highestId) > 0)
                highestId = id;
            String title = elem.getAttribute("title");
            String description = elem.getAttribute("description");
            String level = elem.getAttribute("level");
            String timestamp = elem.getAttribute("timestamp");
			System.out.println("Title : " + title + "\n Description:" + description + " \n Level: " + level + "\n timestamp: " + timestamp + "\n");
            email.send(title, description, level, timestamp);
        }
        if (highestId.compareTo(lastId) > 0)
            persist.setLastId(lastId = highestId);
    }

    /** Prints a usage message and exit. */
    private void usage() {
        System.out.println(
    "Usage: runalerter [-host <lmadmin-host>] [-port <lmadmin-http-port>]\n"+
    "                  [-user <lmadmin-user>] [-password <lmadmin-password>]\n"+
    "                  [-smtpServer <smtp-host>] [-smtpPort <smtp-port>]\n"+
    "                  [-smtpUser <smtp-user>] [-smtpPassword <smtp-password>]\n"+
    "                  [-fromAddress <email-from>] [-toAddress <email-to>]\n"+
    "                  [-persist <alerter-saved-state-file> -interval <seconds>]\n"+
    "\n"+
    "where:\n"+
    "\n"+
    "    -host <lmadmin-host>\n"+
    "        Specifies the host that the lmadmin is running on.\n"+
    "        Defaults to 'localhost'.\n"+
    "\n"+
    "    -port <lmadmin-http-port>\n"+
    "        Specifies the HTTP port that the lmadmin is running on.\n"+
    "        Defaults to '8090'.\n"+
    "\n"+
    "    -user <lmadmin-user>\n"+
    "        Specifies the user that will be used to connect to the lmadmin\n"+
    "        web service.  Defaults to 'alerter'.\n"+
    "\n"+
    "    -password <lmadmin-password>\n"+
    "        Specifies the password that will be used to connect to the\n"+
    "        lmadmin web service.  Defaults to 'alerter'.\n"+
    "\n"+
    "    -smtpServer <smtp-host>\n"+
    "        Specifies the host that the SMTP server is running on.\n"+
    "        Defaults to 'mail'.\n"+
    "\n"+
    "    -smtpPort <smtp-port>\n"+
    "        Specifies the host that the SMTP server is running on.\n"+
    "        Defaults to '25'.\n"+
    "\n"+
    "    -smtpUser <smtp-user>\n"+
    "        Specifies the user that will be used to connect to the SMTP\n"+
    "        mail sever.  Defaults to none.\n"+
     "\n"+
    "    -smtpPassword <smtp-password>\n"+
    "        Specifies the password that will be used to connect to the\n"+
    "        mail sever.  Defaults to none.\n"+
    "\n"+
    "    -fromAddress <email-from>\n"+
    "        Specifies the from address for alert emails.\n"+
    "        Defaults to 'LicenseManagerAlerter'.\n"+
     "\n"+
    "    -toAddress <email-to>\n"+
    "        Specifies the to address for alert emails (normally an alias).\n"+
    "        Defaults to 'LicenseManagerAlerts'.\n"+
    "\n"+
    "    -persist <alerter-saved-state-file>\n"+
    "        The file to save alerter state in (last alert processed).\n"+
    "        Defaults to '../../conf/alerter_state.properties'.\n"+
    "\n"+
    "    -interval <seconds>\n"+
    "        The number of seconds to wait between checks for new alerts.\n"+
    "        Defaults to 300 (five minutes).");

        System.exit(1);
    }

    /** The web service connection */
    private Connection connection;
    
    /** The email sender */
    private Email email;
    
    /** The XML parser generator */
    private DocumentBuilder docBuilder;
    
    /** Alerter state persistence */
    private Persist persist;
    
    /** The last alert ID processed */
    private String lastId;
    
    /** Time to wait between checks for new alerts */
    private int pollInterval = DEFAULT_POLL_INTERVAL;
}
