/*
 *  Copyright (C) 2015 Stichting Akvo (Akvo Foundation)
 *
 *  This file is part of Akvo FLOW.
 *
 *  Akvo FLOW is free software: you can redistribute it and modify it under the terms of
 *  the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
 *  either version 3 of the License or any later version.
 *
 *  Akvo FLOW 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 Affero General Public License included below for more details.
 *
 *  The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
 */

package org.akvo.gae.remoteapi;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.akvo.flow.events.EventLogger;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.tools.remoteapi.RemoteApiInstaller;
import com.google.appengine.tools.remoteapi.RemoteApiOptions;

public class RemoteAPI {

    public static void main(String[] args) {

        if (args.length < 2) {
            System.err
                    .println("Usage: "
                            + RemoteAPI.class.getName()
                            + "<class> <appid> [serviceAccount] [serviceAccountPrivatekey path] [args ...]\n"
                            + "<class> can be a fully qualified class or just a class name."
                            + " Defaults to package org.akvo.gae.remoteapi");
            System.exit(1);
        }

        final boolean isLocalDevelopmentServer = "localhost".equals(args[1]);
        final String className = args[0];
        final String instanceUrl = isLocalDevelopmentServer ? "localhost" : args[1]
                + ".appspot.com";
        final int port = isLocalDevelopmentServer ? 8888 : 443;
        String serviceAccount = null;
        String serviceAccountPvk = null;

        if (!isLocalDevelopmentServer) {
            serviceAccount = args[2];
            serviceAccountPvk = args[3];
        }

        final RemoteApiOptions options = new RemoteApiOptions().server(instanceUrl, port);

        if (isLocalDevelopmentServer) {
            options.useDevelopmentServerCredential();
        } else {
            options.useServiceAccountCredential(serviceAccount, serviceAccountPvk);
        }

        final RemoteApiInstaller installer = new RemoteApiInstaller();

        String orgId = args[1];
        try {
            installer.install(options);
            String clz = className.indexOf(".") != -1 ? className : "org.akvo.gae.remoteapi."
                    + className;
            DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
            DataStoreWithUnilog datastoreServiceWithUnilog = new DataStoreWithUnilog(ds, orgId);
            Process p = (Process) Class.forName(clz).newInstance();
            if (isLocalDevelopmentServer) {
                p.execute(datastoreServiceWithUnilog, Arrays.copyOfRange(args, 2, args.length));
            } else {
                p.execute(datastoreServiceWithUnilog, Arrays.copyOfRange(args, 4, args.length));
                if (datastoreServiceWithUnilog.hasToNotifyUnilog()) {
                    notifyUnilog(orgId, serviceAccountPvk);
                }
            }
            System.out.println("Done");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            installer.uninstall();
        }
    }

    private static void notifyUnilog(String orgId, String serviceAccountPvk) {
        try {
            Path configFile = Paths.get(serviceAccountPvk).getParent().resolve("appengine-web.xml");
            if (configFile.toFile().exists()) {
                String unilogUrl = xpath(configFile, "string(//property[@name='eventNotification']/@value)");
                if (unilogUrl != null && !unilogUrl.equals("")) {
                    System.out.println("Notify Unilog on " + unilogUrl);
                    EventLogger.sendNotificationToUnilog(unilogUrl, orgId);
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
    }

    private static String xpath(Path configFile, String xpathExpression) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(false);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(configFile.toFile());
        XPath xpath = XPathFactory.newInstance().newXPath();
        XPathExpression expr = xpath.compile(xpathExpression);
        return (String) expr.evaluate(doc, XPathConstants.STRING);
    }
}

@@ -2073,32 +2073,64 @@
 (1);%0A        %7D%0A%0A
+        String orgId = args%5B1%5D;%0A
         final bo
@@ -2181,23 +2181,21 @@
 .equals(
-args%5B1%5D
+orgId
 );%0A     
@@ -2307,23 +2307,21 @@
 host%22 : 
-args%5B1%5D
+orgId
 %0A       
@@ -2996,40 +2996,8 @@
 );%0A%0A
-        String orgId = args%5B1%5D;%0A
     

Remove duplicated orgId