/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.run;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.io.Reader;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;

import com.google.common.util.concurrent.MoreExecutors;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.commons.json.JsonObject;
import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.commons.json.JsopReader;
import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.jcr.Jcr;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexTracker;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexEditorProvider;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProvider;
import org.apache.jackrabbit.oak.plugins.index.lucene.hybrid.DocumentQueue;
import org.apache.jackrabbit.oak.run.cli.NodeStoreFixtureProvider;
import org.apache.jackrabbit.oak.run.cli.Options;
import org.apache.jackrabbit.oak.run.commons.Command;
import org.apache.jackrabbit.oak.run.cli.NodeStoreFixture;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.apache.jackrabbit.oak.stats.StatisticsProvider;

public class JsonIndexCommand implements Command {
    public static final String INDEX = "json-index";

    PrintStream output = System.out;
    Session session;
    private boolean interactive;
    private final Map<String, Object> data = new HashMap<String, Object>();

    @Override
    public void execute(String... args) throws Exception {
        OptionParser parser = new OptionParser();
        OptionSpec<String> scriptOption = parser
                .accepts("script", "Path to Script").withOptionalArg()
                .defaultsTo("");
        OptionSpec<String> userOption = parser
                .accepts("user", "User name").withOptionalArg()
                .defaultsTo("admin");
        OptionSpec<String> passwordOption = parser
                .accepts("password", "Password").withOptionalArg()
                .defaultsTo("admin");

        Options oakOptions = new Options();
        OptionSet options = oakOptions.parseAndConfigure(parser, args);

        System.out.println("Opening nodestore...");
        NodeStoreFixture nodeStoreFixture = NodeStoreFixtureProvider.create(oakOptions);

        NodeStore nodeStore = nodeStoreFixture.getStore();
        String script = scriptOption.value(options);
        String user = userOption.value(options);
        String password = passwordOption.value(options);
        LineNumberReader reader = openScriptReader(script);
        try {
            process(nodeStore, reader, user, password);
        } finally {
            nodeStoreFixture.close();
            reader.close();
        }
    }

    private LineNumberReader openScriptReader(String script)
            throws IOException {
        Reader reader;
        if ("-".equals(script)) {
            reader = new InputStreamReader(System.in);
            interactive = true;
        } else {
            reader = new FileReader(script);
        }
        return new LineNumberReader(new BufferedReader(reader));
    }

    public void process(NodeStore nodeStore, LineNumberReader reader, String user, String password)
            throws Exception {
        session = openSession(nodeStore, user, password);
        System.out.println("Nodestore is open");
        if (interactive) {
            System.out.println("Type \"exit\" to quit");
        }
        while (true) {
            try {
                String json = readJson(reader);
                if (json == null || json.trim().equals("exit")) {
                    break;
                }
                execute(json);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (session != null) {
            session.logout();
        }
    }

    private static String readJson(LineNumberReader reader) throws IOException {
        StringBuilder buff = new StringBuilder();
        int level = 0;
        while (true) {
            String line = reader.readLine();
            if (line == null) {
                return null;
            } else if (line.trim().startsWith("//")) {
                continue;
            }
            buff.append(line).append('\n');
            for (int i = 0; i < line.length(); i++) {
                char c = line.charAt(i);
                if (c == '\"') {
                    while (true) {
                        c = line.charAt(++i);
                        if (c == '\"') {
                            break;
                        } else if (c == '\\') {
                            ++i;
                        }
                    }
                } else if (c == '{') {
                    level++;
                } else if (c == '}') {
                    level--;
                }
            }
            if (level == 0 && !buff.toString().trim().isEmpty()) {
                return buff.toString();
            }
        }
    }

    void execute(String command) throws RepositoryException {
        JsopTokenizer t = new JsopTokenizer(command);
        t.read('{');
        JsonObject json = JsonObject.create(t);
        Map<String, String> properties = json.getProperties();
        if (properties.containsKey("if")) {
            Object value = getValueOrVariable(properties.get("if"));
            Object equals = getValueOrVariable(properties.get("="));
            if (value == null) {
                if (equals != null) {
                    return;
                }
            } else if (!value.equals(equals)) {
                return;
            }
        }
        for (Entry<String, String> e : properties.entrySet()) {
            String k = e.getKey();
            Object value = getValueOrVariable(e.getValue());
            if ("addNode".equals(k)) {
                String nodePath = value.toString();
                String parent = PathUtils.getParentPath(nodePath);
                if (session.nodeExists(parent)) {
                    Node p = session.getNode(parent);
                    String nodeName = PathUtils.getName(nodePath);
                    if (!p.hasNode(nodeName)) {
                        JsonObject node = json.getChildren().get("node");
                        addNode(p, nodeName, node);
                    }
                }
            } else if ("removeNode".equals(k)) {
                String path = value.toString();
                if (session.nodeExists(path)) {
                    session.getNode(path).remove();
                }
            } else if ("setProperty".equals(k)) {
                String itemPath = value.toString();
                String nodePath = PathUtils.getParentPath(itemPath);
                if (session.nodeExists(nodePath)) {
                    String propertyName = PathUtils.getName(itemPath);
                    Object propertyValue = getValueOrVariable(properties
                            .get("value"));
                    setProperty(session.getNode(nodePath), propertyName,
                            propertyValue);
                }
            } else if ("session".equals(k)) {
                if ("save".equals(value)) {
                    session.save();
                }
            } else if ("xpath".equals(k) || "sql".equals(k)) {
                String language = "xpath".equals(k) ? k : Query.JCR_SQL2;
                String columnName = "xpath".equals(k) ? "jcr:path" : null;
                boolean quiet = properties.containsKey("quiet");
                int depth = properties.containsKey("depth") ? Integer
                        .parseInt(properties.get("depth")) : 0;
                runQuery(value.toString(), language, columnName, quiet, depth);
            } else if ("print".equals(k)) {
                output.println(value);
            } else if ("for".equals(k)) {
                String name = JsopTokenizer.decodeQuoted(properties.get(k));
                Object old = data.get(name);
                String[] commands = (String[]) getValueOrVariable(properties
                        .get("do"));
                for (String x : (String[]) value) {
                    data.put(name, x);
                    for (String c : commands) {
                        execute(c);
                    }
                }
                data.put(name, old);
            } else if ("loop".equals(k)) {
                while (true) {
                    for (String c : (String[]) value) {
                        execute(c);
                        if (data.remove("$break") != null) {
                            return;
                        }
                    }
                }
            } else if (k.startsWith("$")) {
                setVariable(properties, k, value);
            }
        }
    }

    private void setVariable(Map<String, String> properties, String k,
            Object value) {
        if (k.startsWith("$$")) {
            k = "$" + getValueOrVariable("\"" + k.substring(1) + "\"");
        }
        if (properties.containsKey("+")) {
            Object v2 = getValueOrVariable(properties.get("+"));
            if (value == null) {
                value = v2;
            } else if (v2 == null) {
                // keep value
            } else if (v2 instanceof Long && value instanceof Long) {
                value = (Long) value + (Long) v2;
            } else {
                value = value.toString() + v2.toString();
            }
        }
        data.put(k, value);
    }

    private Object getValueOrVariable(String jsonValue) {
        Object v = getValue(jsonValue);
        if (v == null || !v.toString().startsWith("$")) {
            return v;
        }
        String value = v.toString();
        if (value.startsWith("$$")) {
            value = "$" + getValueOrVariable("\"" + value.substring(1) + "\"");
        }
        return data.get(value.toString());
    }

    private void addNode(Node p, String nodeName, JsonObject json)
            throws RepositoryException {
        Map<String, String> properties = json.getProperties();
        Map<String, JsonObject> children = json.getChildren();
        String primaryType = properties.get("jcr:primaryType");
        Node n;
        if (primaryType == null) {
            n = p.addNode(nodeName);
        } else {
            n = p.addNode(nodeName, getValueOrVariable(primaryType).toString());
        }
        for (Entry<String, String> e : properties.entrySet()) {
            String propertyName = e.getKey();
            if (!"jcr:primaryType".equals(propertyName)) {
                Object value = getValueOrVariable(properties.get(propertyName));
                setProperty(n, propertyName, value);
            }
        }
        for (Entry<String, JsonObject> e : children.entrySet()) {
            String k = e.getKey();
            JsonObject v = e.getValue();
            addNode(n, k, v);
        }
    }

    private static Object getValue(String jsonValue) {
        if (jsonValue == null) {
            return null;
        }
        JsopTokenizer t = new JsopTokenizer(jsonValue);
        if (t.matches(JsopReader.NULL)) {
            return null;
        } else if (t.matches(JsopReader.NUMBER)) {
            String n = t.getToken();
            if (n.indexOf('.') < 0) {
                return Long.parseLong(n);
            }
            return Double.parseDouble(n);
        } else if (t.matches(JsopReader.TRUE)) {
            return true;
        } else if (t.matches(JsopReader.FALSE)) {
            return false;
        } else if (t.matches(JsopReader.STRING)) {
            return t.getToken();
        } else if (t.matches('[')) {
            ArrayList<String> list = new ArrayList<String>();
            if (!t.matches(']')) {
                while (true) {
                    list.add(t.readRawValue());
                    if (t.matches(']')) {
                        break;
                    }
                    t.read(',');
                }
            }
            return list.toArray(new String[0]);
        }
        throw new IllegalArgumentException(jsonValue);
    }

    private static void setProperty(Node n, String propertyName, Object value)
            throws RepositoryException {
        int type = PropertyType.UNDEFINED;
        if (propertyName.startsWith("{")) {
            String t = propertyName.substring(1, propertyName.indexOf('}'));
            propertyName = propertyName.substring(t.length() + 2);
            type = PropertyType.valueFromName(t);
        }
        if (value == null) {
            n.setProperty(propertyName, (String) null);
            return;
        }
        if (type == PropertyType.UNDEFINED) {
            if (value instanceof Boolean) {
                type = PropertyType.BOOLEAN;
            } else if (value instanceof Long) {
                type = PropertyType.LONG;
            } else if (value instanceof Double) {
                type = PropertyType.DOUBLE;
            } else {
                type = PropertyType.STRING;
            }
        }
        if (value instanceof String[]) {
            String[] list = (String[]) value;
            for (int i = 0; i < list.length; i++) {
                list[i] = getValue(list[i]).toString();
            }
            n.setProperty(propertyName, list, type);
        } else {
            n.setProperty(propertyName, value.toString(), type);
        }
    }

    private void runQuery(String query, String language, String columnName,
            boolean quiet, int depth) throws RepositoryException {
        ArrayList<String> list = new ArrayList<String>();
        columnName = query.startsWith("explain") ? "plan" : columnName;
        QueryManager qm = session.getWorkspace().getQueryManager();
        Query q = qm.createQuery(query, language);
        for (String b : q.getBindVariableNames()) {
            ValueFactory vf = session.getValueFactory();
            q.bindValue(b, vf.createValue(data.get("$" + b).toString()));
        }
        QueryResult result = q.execute();
        if (depth != 0) {
            NodeIterator ni = result.getNodes();
            JsopBuilder builder = new JsopBuilder().array();
            while (ni.hasNext()) {
                Node n = ni.nextNode();
                builder.key(n.getPath());
                appendNode(builder, n, depth - 1);
            }
            output.println(JsopBuilder.prettyPrint(builder.endArray().toString()));
            return;
        }
        RowIterator ri = result.getRows();
        while (ri.hasNext()) {
            Row r = ri.nextRow();
            if (columnName != null) {
                String x = r.getValue(columnName).getString();
                list.add(x);
                if (!quiet) {
                    output.println(x);
                }
            } else {
                String[] columnNames = result.getColumnNames();
                for (String cn : columnNames) {
                    Value v = r.getValue(cn);
                    String x = v == null ? null : v.getString();
                    if (columnNames.length == 1) {
                        list.add(x);
                        if (!quiet) {
                            output.println(x);
                        }
                    } else {
                        list.add(x);
                        if (!quiet) {
                            output.println(cn + ": " + x);
                        }
                    }
                }
            }
        }
        data.put("$resultSize", (long) list.size());
        data.put("$result", list.toArray(new String[0]));
    }

    private void appendNode(JsopBuilder builder, Node n, int depth)
            throws RepositoryException {
        builder.object();
        for (PropertyIterator it = n.getProperties(); depth != 0 &&
                it.hasNext();) {
            Property p = it.nextProperty();
            String name = (p.getType() == PropertyType.STRING ||
                    p.getName().equals("jcr:primaryType") ? "" : "{" +
                    PropertyType.nameFromValue(p.getType()) + "}") +
                    p.getName();
            builder.key(name);
            if (p.isMultiple()) {
                builder.array();
                for (Value v : p.getValues()) {
                    builder.value(v.getString());
                }
                builder.endArray();
            } else {
                builder.value(p.getValue().getString());
            }
        }
        for (NodeIterator it = n.getNodes(); depth != 0 && it.hasNext();) {
            Node n2 = it.nextNode();
            builder.key(n2.getName());
            appendNode(builder, n2, depth - 1);
        }
        builder.endObject();
    }

    public static Session openSession(NodeStore nodeStore, String user, String password) throws RepositoryException {
        if (nodeStore == null) {
            return null;
        }
        StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
        Oak oak = new Oak(nodeStore).with(ManagementFactory.getPlatformMBeanServer());
        oak.getWhiteboard().register(StatisticsProvider.class, statisticsProvider, Collections.emptyMap());
        LuceneIndexProvider provider = createLuceneIndexProvider();
        oak.with((QueryIndexProvider) provider)
                .with((Observer) provider)
                .with(createLuceneIndexEditorProvider());
        Jcr jcr = new Jcr(oak);
        Repository repository = jcr.createRepository();
        return repository.login(new SimpleCredentials(user, password.toCharArray()));
    }

    private static LuceneIndexEditorProvider createLuceneIndexEditorProvider() {
        LuceneIndexEditorProvider ep = new LuceneIndexEditorProvider();
        ScheduledExecutorService executorService = MoreExecutors.getExitingScheduledExecutorService(
                (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5));
        StatisticsProvider statsProvider = StatisticsProvider.NOOP;
        int queueSize = Integer.getInteger("queueSize", 1000);
        IndexTracker tracker = new IndexTracker();
        DocumentQueue queue = new DocumentQueue(queueSize, tracker, executorService, statsProvider);
        ep.setIndexingQueue(queue);
        return ep;
    }

    private static LuceneIndexProvider createLuceneIndexProvider() {
        return new LuceneIndexProvider();
    }

}
