/*
 * Copyright 2017 HugeGraph Authors
 *
 * 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 com.baidu.hugegraph.cmd;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;

import com.baidu.hugegraph.base.Printer;
import com.baidu.hugegraph.base.ToolClient;
import com.baidu.hugegraph.base.ToolClient.ConnectionInfo;
import com.baidu.hugegraph.base.ToolManager;
import com.baidu.hugegraph.constant.Constants;
import com.baidu.hugegraph.exception.ExitException;
import com.baidu.hugegraph.manager.AuthBackupRestoreManager;
import com.baidu.hugegraph.manager.BackupManager;
import com.baidu.hugegraph.manager.DumpGraphManager;
import com.baidu.hugegraph.manager.GraphsManager;
import com.baidu.hugegraph.manager.GremlinManager;
import com.baidu.hugegraph.manager.RestoreManager;
import com.baidu.hugegraph.manager.TasksManager;
import com.baidu.hugegraph.structure.Task;
import com.baidu.hugegraph.structure.constant.GraphMode;
import com.baidu.hugegraph.structure.gremlin.Result;
import com.baidu.hugegraph.structure.gremlin.ResultSet;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.ToolUtil;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.ParametersDelegate;
import com.google.common.collect.Lists;

import static com.baidu.hugegraph.manager.BackupManager.BACKUP_DEFAULT_TIMEOUT;

public class HugeGraphCommand {

    private static final int DEFAULT_GRAPH_CLEAR_TIMEOUT = 300;
    private static final int DEFAULT_GRAPH_CREATE_TIMEOUT = 300;

    private SubCommands subCommands;

    private List<ToolManager> taskManagers;

    @ParametersDelegate
    private SubCommands.Url url = new SubCommands.Url();

    @ParametersDelegate
    private SubCommands.Graph graph = new SubCommands.Graph();

    @ParametersDelegate
    private SubCommands.Username username = new SubCommands.Username();

    @ParametersDelegate
    private SubCommands.Password password = new SubCommands.Password();

    @ParametersDelegate
    private SubCommands.Timeout timeout = new SubCommands.Timeout();

    @ParametersDelegate
    private SubCommands.TrustStoreFile trustStoreFile =
                                       new SubCommands.TrustStoreFile();

    @ParametersDelegate
    private SubCommands.TrustStorePassword trustStorePassword =
                                           new SubCommands.TrustStorePassword();

    @ParametersDelegate
    private SubCommands.ThrowMode throwMode = new SubCommands.ThrowMode();

    public HugeGraphCommand() {
        this.subCommands = new SubCommands();
        this.taskManagers = Lists.newArrayList();
    }

    public Map<String, Object> subCommands() {
        return this.subCommands.commands();
    }

    @SuppressWarnings("unchecked")
    public <T> T subCommand(String subCmd) {
        return (T) this.subCommands.commands().get(subCmd);
    }

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

    private void url(String url) {
        this.url.url = url;
    }

    public String graph() {
        return this.graph.graph;
    }

    private void graph(String graph) {
        this.graph.graph = graph;
    }

    public String username() {
        return this.username.username;
    }

    public void username(String username) {
        this.username.username = username;
    }

    public String password() {
        return this.password.password;
    }

    public void password(String password) {
        this.password.password = password;
    }

    public int timeout() {
        return this.timeout.timeout;
    }

    public void timeout(int timeout) {
        this.timeout.timeout = timeout;
    }

    public String trustStoreFile () {
        return this.trustStoreFile.trustStoreFile;
    }

    public void trustStoreFile(String trustStoreFile) {
        this.trustStoreFile.trustStoreFile = trustStoreFile;
    }

    public String trustStorePassword () {
        return this.trustStorePassword.trustStorePassword;
    }

    public void trustStorePassword(String trustStorePassword) {
        this.trustStorePassword.trustStorePassword = trustStorePassword;
    }

    public boolean throwMode() {
        return this.throwMode.throwMode;
    }

    private void throwMode(boolean throwMode) {
        this.throwMode.throwMode = throwMode;
    }

    public JCommander jCommander() {
        JCommander.Builder builder = JCommander.newBuilder();

        // Add main command firstly
        builder.addObject(this);

        // Add sub-commands
        for (Map.Entry<String, Object> entry : this.subCommands().entrySet()) {
            builder.addCommand(entry.getKey(), entry.getValue());
        }

        JCommander jCommander = builder.build();
        jCommander.setProgramName("hugegraph");
        jCommander.setCaseSensitiveOptions(true);
        jCommander.setAllowAbbreviatedOptions(true);
        return jCommander;
    }

    private void execute(String subCmd, JCommander jCommander) {
        this.checkMainParams();
        switch (subCmd) {
            case "backup":
                if (this.timeout() < BACKUP_DEFAULT_TIMEOUT) {
                    this.timeout(BACKUP_DEFAULT_TIMEOUT);
                }
                Printer.print("Graph '%s' start backup!", this.graph());
                SubCommands.Backup backup = this.subCommand(subCmd);
                BackupManager backupManager = manager(BackupManager.class);

                backupManager.init(backup);
                backupManager.backup(backup.types());
                break;
            case "restore":
                GraphsManager graphsManager = manager(GraphsManager.class);
                GraphMode mode = graphsManager.mode(this.graph());
                E.checkState(mode.maintaining(),
                             "Invalid mode '%s' of graph '%s' for restore " +
                             "sub-command", mode, this.graph());
                Printer.print("Graph '%s' start restore in mode '%s'!",
                              this.graph(), mode);
                SubCommands.Restore restore = this.subCommand(subCmd);
                RestoreManager restoreManager = manager(RestoreManager.class);

                restoreManager.init(restore);
                restoreManager.mode(mode);
                restoreManager.restore(restore.types());
                break;
            case "migrate":
                SubCommands.Migrate migrate = this.subCommand(subCmd);
                Printer.print("Migrate graph '%s' from '%s' to '%s' as '%s'",
                              this.graph(), this.url(),
                              migrate.targetUrl(), migrate.targetGraph());

                // Backup source graph
                if (this.timeout() < BACKUP_DEFAULT_TIMEOUT) {
                    this.timeout(BACKUP_DEFAULT_TIMEOUT);
                }
                backup = convMigrate2Backup(migrate);
                backupManager = manager(BackupManager.class);
                backupManager.init(backup);
                backupManager.backup(backup.types());

                // Restore source graph to target graph
                this.url(migrate.targetUrl());
                this.graph(migrate.targetGraph());
                this.username(migrate.targetUsername());
                this.password(migrate.targetPassword());
                this.timeout(migrate.targetTimeout());
                this.trustStoreFile(migrate.targetTrustStoreFile());
                this.trustStorePassword(migrate.targetTrustStorePassword());
                graphsManager = manager(GraphsManager.class);
                GraphMode origin = graphsManager.mode(migrate.targetGraph());
                // Set target graph mode
                mode = migrate.mode();
                E.checkState(mode.maintaining(),
                             "Invalid mode '%s' of graph '%s' for restore",
                             mode, migrate.targetGraph());
                graphsManager.mode(migrate.targetGraph(), mode);
                // Restore
                Printer.print("Graph '%s' start restore in mode '%s'!",
                              migrate.targetGraph(), migrate.mode());
                String directory = backupManager.directory().directory();
                restore = convMigrate2Restore(migrate, directory);
                restoreManager = manager(RestoreManager.class);
                restoreManager.init(restore);
                restoreManager.mode(mode);

                restoreManager.restore(restore.types());
                // Restore target graph mode
                graphsManager.mode(migrate.targetGraph(), origin);
                break;
            case "dump":
                Printer.print("Graph '%s' start dump!", this.graph());
                SubCommands.DumpGraph dump = this.subCommand(subCmd);
                DumpGraphManager dumpManager = manager(DumpGraphManager.class);

                dumpManager.init(dump);
                dumpManager.dumpFormatter(dump.formatter());
                dumpManager.dump();
                break;
            case "graph-create":
                SubCommands.GraphCreate graphCreate = this.subCommand(subCmd);
                if (timeout() < DEFAULT_GRAPH_CREATE_TIMEOUT) {
                    this.timeout(DEFAULT_GRAPH_CREATE_TIMEOUT);
                }
                graphsManager = manager(GraphsManager.class);
                graphsManager.create(graphCreate.name(), graphCreate.config());
                Printer.print("Graph '%s' is created", graphCreate.name());
                break;
            case "graph-clone":
                SubCommands.GraphClone graphClone = this.subCommand(subCmd);
                if (timeout() < DEFAULT_GRAPH_CREATE_TIMEOUT) {
                    this.timeout(DEFAULT_GRAPH_CREATE_TIMEOUT);
                }
                graphsManager = manager(GraphsManager.class);
                graphsManager.clone(graphClone.name(),
                                    graphClone.cloneGraphName());
                Printer.print("Graph '%s' is created(cloned from '%s')",
                              graphClone.name(), graphClone.cloneGraphName());
                break;
            case "graph-list":
                graphsManager = manager(GraphsManager.class);
                Printer.printList("Graphs", graphsManager.list());
                break;
            case "graph-get":
                graphsManager = manager(GraphsManager.class);
                Printer.printMap("Graph info",
                                 graphsManager.get(this.graph()));
                break;
            case "graph-clear":
                SubCommands.GraphClear graphClear = this.subCommand(subCmd);
                if (timeout() < DEFAULT_GRAPH_CLEAR_TIMEOUT) {
                    this.timeout(DEFAULT_GRAPH_CLEAR_TIMEOUT);
                }
                graphsManager = manager(GraphsManager.class);
                graphsManager.clear(this.graph(), graphClear.confirmMessage());
                Printer.print("Graph '%s' is cleared", this.graph());
                break;
            case "graph-drop":
                SubCommands.GraphDrop graphDrop = this.subCommand(subCmd);
                if (timeout() < DEFAULT_GRAPH_CLEAR_TIMEOUT) {
                    this.timeout(DEFAULT_GRAPH_CLEAR_TIMEOUT);
                }
                graphsManager = manager(GraphsManager.class);
                graphsManager.drop(this.graph(), graphDrop.confirmMessage());
                Printer.print("Graph '%s' is dropped", this.graph());
                break;
            case "graph-mode-set":
                SubCommands.GraphModeSet graphModeSet = this.subCommand(subCmd);
                graphsManager = manager(GraphsManager.class);
                graphsManager.mode(this.graph(), graphModeSet.mode());
                Printer.print("Set graph '%s' mode to '%s'",
                              this.graph(), graphModeSet.mode());
                break;
            case "graph-mode-get":
                graphsManager = manager(GraphsManager.class);
                Printer.printKV("Graph mode", graphsManager.mode(this.graph()));
                break;
            case "gremlin-execute":
                SubCommands.Gremlin gremlin = this.subCommand(subCmd);
                GremlinManager gremlinManager = manager(GremlinManager.class);
                Printer.print("Run gremlin script");
                ResultSet result = gremlinManager.execute(gremlin.script(),
                                                          gremlin.bindings(),
                                                          gremlin.language(),
                                                          gremlin.aliases());
                Iterator<Result> iterator = result.iterator();
                while (iterator.hasNext()) {
                    Printer.print(iterator.next().getString());
                }
                break;
            case "gremlin-schedule":
                SubCommands.GremlinJob job = this.subCommand(subCmd);
                gremlinManager = manager(GremlinManager.class);
                Printer.print("Run gremlin script as async job");
                long taskId = gremlinManager.executeAsTask(job.script(),
                                                           job.bindings(),
                                                           job.language());
                Printer.printKV("Task id", taskId);
                break;
            case "task-list":
                SubCommands.TaskList taskList = this.subCommand(subCmd);
                TasksManager tasksManager = manager(TasksManager.class);
                List<Task> tasks = tasksManager.list(taskList.status(),
                                                     taskList.limit());
                List<Object> results = tasks.stream().map(Task::asMap)
                                            .collect(Collectors.toList());
                Printer.printList("Tasks", results);
                break;
            case "task-get":
                SubCommands.TaskGet taskGet = this.subCommand(subCmd);
                tasksManager = manager(TasksManager.class);
                Printer.printKV("Task info",
                                tasksManager.get(taskGet.taskId()).asMap());
                break;
            case "task-delete":
                SubCommands.TaskDelete taskDelete = this.subCommand(subCmd);
                tasksManager = manager(TasksManager.class);
                tasksManager.delete(taskDelete.taskId());
                Printer.print("Task '%s' is deleted", taskDelete.taskId());
                break;
            case "task-cancel":
                SubCommands.TaskCancel taskCancel = this.subCommand(subCmd);
                tasksManager = manager(TasksManager.class);
                tasksManager.cancel(taskCancel.taskId());
                Printer.print("Task '%s' is cancelled", taskCancel.taskId());
                break;
            case "task-clear":
                SubCommands.TaskClear taskClear = this.subCommand(subCmd);
                tasksManager = manager(TasksManager.class);
                tasksManager.clear(taskClear.force());
                Printer.print("Tasks are cleared[force=%s]",
                              taskClear.force());
                break;
            case "auth-backup":
                Printer.print("Auth backup start...");
                SubCommands.AuthBackup authBackup = this.subCommand(subCmd);
                AuthBackupRestoreManager authBackupManager = manager(AuthBackupRestoreManager.class);

                authBackupManager.init(authBackup);
                authBackupManager.backup(authBackup.types());
                break;
            case "auth-restore":
                Printer.print("Auth restore start...");
                SubCommands.AuthRestore authRestore = this.subCommand(subCmd);
                AuthBackupRestoreManager authRestoreManager = manager(AuthBackupRestoreManager.class);

                authRestoreManager.init(authRestore);
                authRestoreManager.restore(authRestore.types());
                break;
            default:
                throw new ParameterException(String.format(
                          "Invalid sub-command: %s", subCmd));
        }
    }

    private void execute(String[] args) {
        JCommander jCommander = this.parseCommand(args);
        this.execute(jCommander.getParsedCommand(), jCommander);
    }

    private void checkMainParams() {
        E.checkArgument(this.url() != null, "Url can't be null");
        E.checkArgument(this.username() == null && this.password() == null ||
                        this.username() != null && this.password() != null,
                        "Both user name and password must be null or " +
                        "not null at same time");
    }

    private <T extends ToolManager> T manager(Class<T> clz) {
        try {
            ConnectionInfo info = new ConnectionInfo(this.url(), this.graph(),
                                                     this.username(),
                                                     this.password(),
                                                     this.timeout(),
                                                     this.trustStoreFile(),
                                                     this.trustStorePassword());
            T toolManager = clz.getConstructor(ToolClient.ConnectionInfo.class)
                               .newInstance(info);
            this.taskManagers.add(toolManager);
            return toolManager;
        } catch (Exception e) {
            throw new RuntimeException(String.format(
                      "Construct manager failed for class '%s', please make " +
                      "sure global arguments set correctly: " +
                      "--url=%s,--graph=%s,--user=%s,--password=%s," +
                      "--timeout=%s,--trust-store-file=%s," +
                      "--trust-store-password=%s", clz.getSimpleName(),
                      this.url(), this.graph(), this.username(),
                      this.password(), this.timeout(),
                      this.trustStoreFile(), this.trustStorePassword()), e);
        }
    }

    private static SubCommands.Backup convMigrate2Backup(
                                      SubCommands.Migrate migrate) {
        SubCommands.Backup backup = new SubCommands.Backup();
        backup.splitSize(migrate.splitSize());
        backup.directory(migrate.directory());
        backup.logDir(migrate.logDir());
        backup.types(migrate.types());
        backup.retry(migrate.retry());
        backup.hdfsConf(migrate.hdfsConf());
        return backup;
    }

    private static SubCommands.Restore convMigrate2Restore(
                                       SubCommands.Migrate migrate,
                                       String directory) {
        SubCommands.Restore restore = new SubCommands.Restore();
        restore.clean(!migrate.keepData());
        restore.directory(directory);
        restore.logDir(migrate.logDir());
        restore.types(migrate.types());
        restore.retry(migrate.retry());
        restore.hdfsConf(migrate.hdfsConf());
        return restore;
    }

    private GraphMode mode() {
        GraphsManager graphsManager = manager(GraphsManager.class);
        GraphMode mode = graphsManager.mode(this.graph());
        E.checkState(mode.maintaining(),
                     "Invalid mode '%s' of graph '%s' for restore " +
                     "sub-command", mode, this.graph());
        return mode;
    }

    public JCommander parseCommand(String[] args) {
        JCommander jCommander = this.jCommander();
        if (args.length == 0) {
            throw ExitException.exception(ToolUtil.commandUsage(jCommander),
                                          "No command found, please input" +
                                          " command");
        }
        if (this.parseHelp(args, jCommander)) {
            assert false;
        } else {
            jCommander.parse(args);
        }
        String subCommand = jCommander.getParsedCommand();
        if (subCommand == null) {
            throw ExitException.normal(ToolUtil.commandsCategory(
                                       jCommander),
                                       "No sub-command found");
        }
        return jCommander;
    }

    public boolean parseHelp(String[] args, JCommander jCommander) {
        String subCommand = Strings.EMPTY;
        List<String> list = Arrays.asList(args);
        if (!list.contains(Constants.COMMAND_HELP)) {
            return false;
        }
        // Parse the '--throw-mode' command
        if (list.contains(Constants.COMMAND_THROW_MODE)) {
            int index = list.indexOf(Constants.COMMAND_THROW_MODE) + 1;
            jCommander.parse(Constants.COMMAND_THROW_MODE,
                             list.get(index));
        }
        int index = list.indexOf(Constants.COMMAND_HELP);
        if (list.size() > index + 1) {
            subCommand = list.get(index + 1);
        }
        if (StringUtils.isEmpty(subCommand)) {
            throw ExitException.normal(ToolUtil.commandUsage(jCommander),
                                       "Command : hugegragh help");
        }

        Map<String, JCommander> commands = jCommander.getCommands();
        if (commands.containsKey(subCommand)) {
            throw ExitException.normal(ToolUtil.commandUsage(
                                       commands.get(subCommand)),
                                       "Command : hugegragh help %s",
                                       subCommand);
        } else {
            throw ExitException.exception(ToolUtil.commandsCategory(jCommander),
                                          "Unexpected help sub-command " +
                                          "%s", subCommand);
        }
    }

    public void shutdown() {
        if (CollectionUtils.isEmpty(this.taskManagers)) {
            return;
        }
        for (ToolManager toolManager : this.taskManagers) {
            toolManager.close();
        }
    }

    public static void main(String[] args) {
        HugeGraphCommand cmd = new HugeGraphCommand();
        int exitCode = Constants.EXIT_CODE_NORMAL;
        try {
            cmd.execute(args);
        } catch (ExitException e) {
            exitCode = e.exitCode();
            ToolUtil.exitOrThrow(e, cmd.throwMode());
        } catch (Throwable e) {
            exitCode = Constants.EXIT_CODE_ERROR;
            ToolUtil.printOrThrow(e, cmd.throwMode());
        } finally {
            cmd.shutdown();
        }

        if (exitCode != Constants.EXIT_CODE_NORMAL) {
            System.exit(exitCode);
        }
    }
}
