/*
 * 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.accumulo.shell.commands;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.NamespaceNotFoundException;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.client.impl.Namespaces;
import org.apache.accumulo.core.client.impl.Tables;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.accumulo.core.util.BadArgumentException;
import org.apache.accumulo.shell.Shell;
import org.apache.accumulo.shell.Shell.Command;
import org.apache.accumulo.shell.Shell.PrintFile;
import org.apache.accumulo.shell.ShellOptions;
import org.apache.accumulo.shell.Token;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;

import jline.console.ConsoleReader;

public class ConfigCommand extends Command {
  private Option tableOpt, deleteOpt, setOpt, filterOpt, disablePaginationOpt, outputFileOpt,
      namespaceOpt;

  private int COL1 = 10, COL2 = 7;
  private ConsoleReader reader;

  @Override
  public void registerCompletion(final Token root,
      final Map<Command.CompletionSet,Set<String>> completionSet) {
    final Token cmd = new Token(getName());
    final Token sub = new Token("-" + setOpt.getOpt());
    for (Property p : Property.values()) {
      if (!(p.getKey().endsWith(".")) && !p.isExperimental()) {
        sub.addSubcommand(new Token(p.toString()));
      }
    }
    cmd.addSubcommand(sub);
    root.addSubcommand(cmd);
  }

  @Override
  public int execute(final String fullCommand, final CommandLine cl, final Shell shellState)
      throws AccumuloException, AccumuloSecurityException, TableNotFoundException, IOException,
      ClassNotFoundException, NamespaceNotFoundException {
    reader = shellState.getReader();

    final String tableName = cl.getOptionValue(tableOpt.getOpt());
    if (tableName != null && !shellState.getConnector().tableOperations().exists(tableName)) {
      throw new TableNotFoundException(null, tableName, null);
    }
    final String namespace = cl.getOptionValue(namespaceOpt.getOpt());
    if (namespace != null && !shellState.getConnector().namespaceOperations().exists(namespace)) {
      throw new NamespaceNotFoundException(null, namespace, null);
    }
    if (cl.hasOption(deleteOpt.getOpt())) {
      // delete property from table
      String property = cl.getOptionValue(deleteOpt.getOpt());
      if (property.contains("=")) {
        throw new BadArgumentException("Invalid '=' operator in delete operation.", fullCommand,
            fullCommand.indexOf('='));
      }
      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property
              + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().tableOperations().removeProperty(tableName, property);
        Shell.log.debug("Successfully deleted table configuration option.");
      } else if (namespace != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property
              + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().namespaceOperations().removeProperty(namespace, property);
        Shell.log.debug("Successfully deleted namespace configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          Shell.log.warn("Invalid per-table property : " + property
              + ", still removing from zookeeper if it's there.");
        }
        shellState.getConnector().instanceOperations().removeProperty(property);
        Shell.log.debug("Successfully deleted system configuration option");
      }
    } else if (cl.hasOption(setOpt.getOpt())) {
      // set property on table
      String property = cl.getOptionValue(setOpt.getOpt()), value = null;
      if (!property.contains("=")) {
        throw new BadArgumentException("Missing '=' operator in set operation.", fullCommand,
            fullCommand.indexOf(property));
      }
      final String pair[] = property.split("=", 2);
      property = pair[0];
      value = pair[1];

      if (tableName != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          throw new BadArgumentException("Invalid per-table property.", fullCommand,
              fullCommand.indexOf(property));
        }
        if (property.equals(Property.TABLE_DEFAULT_SCANTIME_VISIBILITY.getKey())) {
          new ColumnVisibility(value); // validate that it is a valid expression
        }
        shellState.getConnector().tableOperations().setProperty(tableName, property, value);
        Shell.log.debug("Successfully set table configuration option.");
      } else if (namespace != null) {
        if (!Property.isValidTablePropertyKey(property)) {
          throw new BadArgumentException("Invalid per-table property.", fullCommand,
              fullCommand.indexOf(property));
        }
        if (property.equals(Property.TABLE_DEFAULT_SCANTIME_VISIBILITY.getKey())) {
          new ColumnVisibility(value); // validate that it is a valid expression
        }
        shellState.getConnector().namespaceOperations().setProperty(namespace, property, value);
        Shell.log.debug("Successfully set table configuration option.");
      } else {
        if (!Property.isValidZooPropertyKey(property)) {
          throw new BadArgumentException("Property cannot be modified in zookeeper", fullCommand,
              fullCommand.indexOf(property));
        }
        shellState.getConnector().instanceOperations().setProperty(property, value);
        Shell.log.debug("Successfully set system configuration option");
      }
    } else {
      // display properties
      final TreeMap<String,String> systemConfig = new TreeMap<>();
      systemConfig.putAll(shellState.getConnector().instanceOperations().getSystemConfiguration());

      final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
      final PrintFile printFile = outputFile == null ? null : new PrintFile(outputFile);

      final TreeMap<String,String> siteConfig = new TreeMap<>();
      siteConfig.putAll(shellState.getConnector().instanceOperations().getSiteConfiguration());

      final TreeMap<String,String> defaults = new TreeMap<>();
      for (Entry<String,String> defaultEntry : AccumuloConfiguration.getDefaultConfiguration()) {
        defaults.put(defaultEntry.getKey(), defaultEntry.getValue());
      }

      final TreeMap<String,String> namespaceConfig = new TreeMap<>();
      if (tableName != null) {
        String n = Namespaces.getNamespaceName(shellState.getInstance(), Tables.getNamespaceId(
            shellState.getInstance(), Tables.getTableId(shellState.getInstance(), tableName)));
        for (Entry<String,String> e : shellState.getConnector().namespaceOperations()
            .getProperties(n)) {
          namespaceConfig.put(e.getKey(), e.getValue());
        }
      }

      Iterable<Entry<String,String>> acuconf =
          shellState.getConnector().instanceOperations().getSystemConfiguration().entrySet();
      if (tableName != null) {
        acuconf = shellState.getConnector().tableOperations().getProperties(tableName);
      } else if (namespace != null) {
        acuconf = shellState.getConnector().namespaceOperations().getProperties(namespace);
      }
      final TreeMap<String,String> sortedConf = new TreeMap<>();
      for (Entry<String,String> propEntry : acuconf) {
        sortedConf.put(propEntry.getKey(), propEntry.getValue());
      }

      for (Entry<String,String> propEntry : acuconf) {
        final String key = propEntry.getKey();
        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt())
            && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if ((tableName != null || namespace != null) && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        COL2 = Math.max(COL2, propEntry.getKey().length() + 3);
      }

      final ArrayList<String> output = new ArrayList<>();
      printConfHeader(output);

      for (Entry<String,String> propEntry : sortedConf.entrySet()) {
        final String key = propEntry.getKey();

        // only show properties with similar names to that
        // specified, or all of them if none specified
        if (cl.hasOption(filterOpt.getOpt())
            && !key.contains(cl.getOptionValue(filterOpt.getOpt()))) {
          continue;
        }
        if ((tableName != null || namespace != null) && !Property.isValidTablePropertyKey(key)) {
          continue;
        }
        String siteVal = siteConfig.get(key);
        String sysVal = systemConfig.get(key);
        String curVal = propEntry.getValue();
        String dfault = defaults.get(key);
        String nspVal = namespaceConfig.get(key);
        boolean printed = false;

        if (dfault != null && key.toLowerCase().contains("password")) {
          siteVal = sysVal = dfault = curVal = curVal.replaceAll(".", "*");
        }
        if (sysVal != null) {
          if (defaults.containsKey(key) && !Property.getPropertyByKey(key).isExperimental()) {
            printConfLine(output, "default", key, dfault);
            printed = true;
          }
          if (!defaults.containsKey(key) || !defaults.get(key).equals(siteVal)) {
            printConfLine(output, "site", printed ? "   @override" : key,
                siteVal == null ? "" : siteVal);
            printed = true;
          }
          if (!siteConfig.containsKey(key) || !siteVal.equals(sysVal)) {
            printConfLine(output, "system", printed ? "   @override" : key, sysVal);
            printed = true;
          }

        }
        if (nspVal != null) {
          if (!systemConfig.containsKey(key) || !sysVal.equals(nspVal)) {
            printConfLine(output, "namespace", printed ? "   @override" : key, nspVal);
            printed = true;
          }
        }

        // show per-table value only if it is different (overridden)
        if (tableName != null && !curVal.equals(nspVal)) {
          printConfLine(output, "table", printed ? "   @override" : key, curVal);
        } else if (namespace != null && !curVal.equals(sysVal)) {
          printConfLine(output, "namespace", printed ? "   @override" : key, curVal);
        }
      }
      printConfFooter(output);
      shellState.printLines(output.iterator(), !cl.hasOption(disablePaginationOpt.getOpt()),
          printFile);
      if (printFile != null) {
        printFile.close();
      }
    }
    return 0;
  }

  private void printConfHeader(List<String> output) {
    printConfFooter(output);
    output.add(String.format("%-" + COL1 + "s | %-" + COL2 + "s | %s", "SCOPE", "NAME", "VALUE"));
    printConfFooter(output);
  }

  private void printConfLine(List<String> output, String s1, String s2, String s3) {
    if (s2.length() < COL2) {
      s2 += " " + Shell.repeat(".", COL2 - s2.length() - 1);
    }
    output.add(String.format("%-" + COL1 + "s | %-" + COL2 + "s | %s", s1, s2, s3.replace("\n",
        "\n" + Shell.repeat(" ", COL1 + 1) + "|" + Shell.repeat(" ", COL2 + 2) + "|" + " ")));
  }

  private void printConfFooter(List<String> output) {
    int col3 =
        Math.max(1, Math.min(Integer.MAX_VALUE, reader.getTerminal().getWidth() - COL1 - COL2 - 6));
    output.add(String.format("%" + COL1 + "s-+-%" + COL2 + "s-+-%-" + col3 + "s",
        Shell.repeat("-", COL1), Shell.repeat("-", COL2), Shell.repeat("-", col3)));
  }

  @Override
  public String description() {
    return "prints system properties and table specific properties";
  }

  @Override
  public Options getOptions() {
    final Options o = new Options();
    final OptionGroup og = new OptionGroup();
    final OptionGroup tgroup = new OptionGroup();

    tableOpt = new Option(ShellOptions.tableOption, "table", true,
        "table to display/set/delete properties for");
    deleteOpt = new Option("d", "delete", true, "delete a per-table property");
    setOpt = new Option("s", "set", true, "set a per-table property");
    filterOpt = new Option("f", "filter", true, "show only properties that contain this string");
    disablePaginationOpt =
        new Option("np", "no-pagination", false, "disables pagination of output");
    outputFileOpt = new Option("o", "output", true, "local file to write the scan output to");
    namespaceOpt = new Option(ShellOptions.namespaceOption, "namespace", true,
        "namespace to display/set/delete properties for");

    tableOpt.setArgName("table");
    deleteOpt.setArgName("property");
    setOpt.setArgName("property=value");
    filterOpt.setArgName("string");
    outputFileOpt.setArgName("file");
    namespaceOpt.setArgName("namespace");

    og.addOption(deleteOpt);
    og.addOption(setOpt);
    og.addOption(filterOpt);

    tgroup.addOption(tableOpt);
    tgroup.addOption(namespaceOpt);

    o.addOptionGroup(tgroup);
    o.addOptionGroup(og);
    o.addOption(disablePaginationOpt);
    o.addOption(outputFileOpt);

    return o;
  }

  @Override
  public int numArgs() {
    return 0;
  }
}
