// Copyright (C) 2009 The Android Open Source Project
//
// Licensed 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.google.gerrit.pgm.init.api;

import com.google.gerrit.common.Die;
import java.io.Console;
import java.util.EnumSet;
import java.util.Set;

/** Console based interaction with the invoking user. */
public abstract class ConsoleUI {
  /** Get a UI instance, assuming interactive mode. */
  public static ConsoleUI getInstance() {
    return getInstance(false);
  }

  /** Get a UI instance, possibly forcing batch mode. */
  public static ConsoleUI getInstance(final boolean batchMode) {
    Console console = batchMode ? null : System.console();
    return console != null ? new Interactive(console) : new Batch();
  }

  /** Constructs an exception indicating the user aborted the operation. */
  protected static Die abort() {
    return new Die("aborted by user");
  }

  /** @return true if this is a batch UI that has no user interaction. */
  public abstract boolean isBatch();

  /** Display a header message before a series of prompts. */
  public abstract void header(String fmt, Object... args);

  /** Display a message. */
  public abstract void message(String fmt, Object... args);

  /** Request the user to answer a yes/no question. */
  public abstract boolean yesno(Boolean def, String fmt, Object... args);

  /** Prints a message asking the user to let us know when its safe to continue. */
  public abstract void waitForUser();

  /** Prompt the user for a string, suggesting a default, and returning choice. */
  public abstract String readString(String def, String fmt, Object... args);

  /** Prompt the user to make a choice from an allowed list of values. */
  public abstract String readString(
      String def, Set<String> allowedValues, String fmt, Object... args);

  /** Prompt the user for an integer value, suggesting a default. */
  public int readInt(int def, String fmt, Object... args) {
    for (; ; ) {
      String p = readString(String.valueOf(def), fmt, args);
      try {
        return Integer.parseInt(p.trim(), 10);
      } catch (NumberFormatException e) {
        System.err.println("error: Invalid integer format: " + p.trim());
      }
    }
  }

  /** Prompt the user for a password, returning the string; null if blank. */
  public abstract String password(String fmt, Object... args);

  /** Display an error message on the system stderr. */
  public void error(String format, Object... args) {
    System.err.println(String.format(format, args));
    System.err.flush();
  }

  /** Prompt the user to make a choice from an enumeration's values. */
  public abstract <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
      T def, A options, String fmt, Object... args);

  private static class Interactive extends ConsoleUI {
    private final Console console;

    Interactive(final Console console) {
      this.console = console;
    }

    @Override
    public boolean isBatch() {
      return false;
    }

    @Override
    public boolean yesno(Boolean def, String fmt, Object... args) {
      final String prompt = String.format(fmt, args);
      for (; ; ) {
        String y = "y";
        String n = "n";
        if (def != null) {
          if (def) {
            y = "Y";
          } else {
            n = "N";
          }
        }

        String yn = console.readLine("%-30s [%s/%s]? ", prompt, y, n);
        if (yn == null) {
          throw abort();
        }
        yn = yn.trim();
        if (def != null && yn.isEmpty()) {
          return def;
        }
        if (yn.equalsIgnoreCase("y") || yn.equalsIgnoreCase("yes")) {
          return true;
        }
        if (yn.equalsIgnoreCase("n") || yn.equalsIgnoreCase("no")) {
          return false;
        }
      }
    }

    @Override
    public void waitForUser() {
      if (console.readLine("Press enter to continue ") == null) {
        throw abort();
      }
    }

    @Override
    public String readString(String def, String fmt, Object... args) {
      final String prompt = String.format(fmt, args);
      String r;
      if (def != null) {
        r = console.readLine("%-30s [%s]: ", prompt, def);
      } else {
        r = console.readLine("%-30s : ", prompt);
      }
      if (r == null) {
        throw abort();
      }
      r = r.trim();
      if (r.isEmpty()) {
        return def;
      }
      return r;
    }

    @Override
    public String readString(String def, Set<String> allowedValues, String fmt, Object... args) {
      for (; ; ) {
        String r = readString(def, fmt, args);
        if (allowedValues.contains(r.toLowerCase())) {
          return r.toLowerCase();
        }
        if (!"?".equals(r)) {
          console.printf("error: '%s' is not a valid choice\n", r);
        }
        console.printf("       Supported options are:\n");
        for (final String v : allowedValues) {
          console.printf("         %s\n", v.toLowerCase());
        }
      }
    }

    @Override
    public String password(String fmt, Object... args) {
      final String prompt = String.format(fmt, args);
      for (; ; ) {
        final char[] a1 = console.readPassword("%-30s : ", prompt);
        if (a1 == null) {
          throw abort();
        }

        final char[] a2 = console.readPassword("%30s : ", "confirm password");
        if (a2 == null) {
          throw abort();
        }

        final String s1 = new String(a1);
        final String s2 = new String(a2);
        if (!s1.equals(s2)) {
          console.printf("error: Passwords did not match; try again\n");
          continue;
        }
        return !s1.isEmpty() ? s1 : null;
      }
    }

    @Override
    public <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
        T def, A options, String fmt, Object... args) {
      final String prompt = String.format(fmt, args);
      for (; ; ) {
        String r = console.readLine("%-30s [%s/?]: ", prompt, def.toString());
        if (r == null) {
          throw abort();
        }
        r = r.trim();
        if (r.isEmpty()) {
          return def;
        }
        for (final T e : options) {
          if (e.toString().equalsIgnoreCase(r)) {
            return e;
          }
        }
        if (!"?".equals(r)) {
          console.printf("error: '%s' is not a valid choice\n", r);
        }
        console.printf("       Supported options are:\n");
        for (final T e : options) {
          console.printf("         %s\n", e.toString().toLowerCase());
        }
      }
    }

    @Override
    public void header(String fmt, Object... args) {
      fmt = fmt.replaceAll("\n", "\n*** ");
      console.printf("\n*** " + fmt + "\n*** \n\n", args);
    }

    @Override
    public void message(String fmt, Object... args) {
      console.printf(fmt, args);
    }
  }

  private static class Batch extends ConsoleUI {
    @Override
    public boolean isBatch() {
      return true;
    }

    @Override
    public boolean yesno(Boolean def, String fmt, Object... args) {
      return def != null ? def : true;
    }

    @Override
    public String readString(String def, String fmt, Object... args) {
      return def;
    }

    @Override
    public String readString(String def, Set<String> allowedValues, String fmt, Object... args) {
      return def;
    }

    @Override
    public void waitForUser() {}

    @Override
    public String password(String fmt, Object... args) {
      return null;
    }

    @Override
    public <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
        T def, A options, String fmt, Object... args) {
      return def;
    }

    @Override
    public void header(String fmt, Object... args) {}

    @Override
    public void message(String fmt, Object... args) {}
  }
}
