// 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.util;

import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;

import java.io.Console;
import java.lang.reflect.InvocationTargetException;

/** 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");
  }

  /** Obtain all values from an enumeration. */
  @SuppressWarnings("unchecked")
  protected static <T extends Enum<?>> T[] all(final T value) {
    try {
      return (T[]) value.getClass().getMethod("values").invoke(null);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
    } catch (SecurityException e) {
      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
    } catch (IllegalAccessException e) {
      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
    } catch (InvocationTargetException e) {
      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
    }
  }

  /** @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);

  /** 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 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);

  /** Prompt the user to make a choice from an enumeration's values. */
  public abstract <T extends Enum<?>> T readEnum(T def, 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 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<?>> T readEnum(T def, String fmt, Object... args) {
      final String prompt = String.format(fmt, args);
      final T[] options = all(def);
      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 (equalsIgnoreCase(e.toString(), 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);
    }
  }

  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 void waitForUser() {
    }

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

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

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