// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.syntax;

import com.google.common.base.Strings;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrintable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
import java.io.IOException;
import java.util.Arrays;
import java.util.Formattable;
import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;
import java.util.MissingFormatWidthException;
import java.util.UnknownFormatConversionException;
import javax.annotation.Nullable;

/** (Pretty) Printing of Skylark values */
public class Printer {

  /**
   * Creates an instance of {@link BasePrinter} that wraps an existing buffer.
   *
   * @param buffer an {@link Appendable}
   * @return new {@link BasePrinter}
   */
  static BasePrinter getPrinter(Appendable buffer) {
    return new BasePrinter(buffer);
  }

  /**
   * Creates an instance of {@link BasePrinter} with an empty buffer.
   *
   * @return new {@link BasePrinter}
   */
  public static BasePrinter getPrinter() {
    return new BasePrinter(new StringBuilder());
  }

  /**
   * Creates an instance of {@link PrettyPrinter} with an empty buffer.
   *
   * @return new {@link PrettyPrinter}
   */
  public static PrettyPrinter getPrettyPrinter() {
    return new PrettyPrinter(new StringBuilder());
  }

  /**
   * Creates an instance of {@link BasePrinter} with an empty buffer and whose format strings allow
   * only %s and %%.
   */
  public static BasePrinter getSimplifiedPrinter() {
    return new BasePrinter(new StringBuilder(), /*simplifiedFormatStrings=*/ true);
  }

  private Printer() {}

  // These static methods proxy to the similar methods of BasePrinter

  /**
   * Format an object with Skylark's {@code debugPrint}.
   */
  public static String debugPrint(Object x) {
    return getPrinter().debugPrint(x).toString();
  }

  /**
   * Format an object with Skylark's {@code str}.
   */
  public static String str(Object x) {
    return getPrinter().str(x).toString();
  }

  /**
   * Format an object with Skylark's {@code repr}.
   */
  public static String repr(Object x) {
    return getPrinter().repr(x).toString();
  }


  /**
   * Perform Python-style string formatting, as per pattern % tuple Limitations: only %d %s %r %%
   * are supported.
   *
   * @param pattern a format string.
   * @param arguments an array containing positional arguments.
   * @return the formatted string.
   */
  public static String format(String pattern, Object... arguments) {
    return getPrinter().format(pattern, arguments).toString();
  }

  /**
   * Perform Python-style string formatting, as per pattern % tuple Limitations: only %d %s %r %%
   * are supported.
   *
   * @param pattern a format string.
   * @param arguments a tuple containing positional arguments.
   * @return the formatted string.
   */
  public static String formatWithList(String pattern, List<?> arguments) {
    return getPrinter().formatWithList(pattern, arguments).toString();
  }

  /**
   * Perform Python-style string formatting, lazily.
   *
   * @param pattern a format string.
   * @param arguments positional arguments.
   * @return the formatted string.
   */
  public static Formattable formattable(final String pattern, Object... arguments) {
    final List<Object> args = Arrays.asList(arguments);
    return new Formattable() {
      @Override
      public String toString() {
        return formatWithList(pattern, args);
      }

      @Override
      public void formatTo(Formatter formatter, int flags, int width, int precision) {
        Printer.getPrinter(formatter.out()).formatWithList(pattern, args);
      }
    };
  }

  /**
   * Append a char to a buffer. In case of {@link IOException} throw an {@link AssertionError}
   * instead
   *
   * @return buffer
   */
  public static Appendable append(Appendable buffer, char c) {
    try {
      return buffer.append(c);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /**
   * Append a char sequence to a buffer. In case of {@link IOException} throw an
   * {@link AssertionError} instead
   *
   * @return buffer
   */
  public static Appendable append(Appendable buffer, CharSequence s) {
    try {
      return buffer.append(s);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /**
   * Append a char sequence range to a buffer. In case of {@link IOException} throw an
   * {@link AssertionError} instead
   * @return buffer
   */
  private static Appendable append(Appendable buffer, CharSequence s, int start, int end) {
    try {
      return buffer.append(s, start, end);
    } catch (IOException e) {
      throw new AssertionError(e);
    }
  }

  /** Actual class that implements Printer API */
  public static class BasePrinter implements SkylarkPrinter {
    // Methods of this class should not recurse through static methods of Printer

    protected final Appendable buffer;

    /**
     * If true, the only percent sequences allowed in format strings are %s substitutions and %%
     * escapes.
     */
    protected final boolean simplifiedFormatStrings;

    /**
     * Creates a printer.
     *
     * @param buffer the {@link Appendable} that will be written to
     * @param simplifiedFormatStrings if true, format strings will allow only %s and %%
     */
    protected BasePrinter(Appendable buffer, boolean simplifiedFormatStrings) {
      this.buffer = buffer;
      this.simplifiedFormatStrings = simplifiedFormatStrings;
    }

    /**
     * Creates a printer that writes to the given buffer and that does not use simplified format
     * strings.
     */
    protected BasePrinter(Appendable buffer) {
      this(buffer, /*simplifiedFormatStrings=*/ false);
    }

    /**
     * Creates a printer that uses a fresh buffer and that does not use simplified format strings.
     */
    protected BasePrinter() {
      this(new StringBuilder());
    }

    @Override
    public String toString() {
      return buffer.toString();
    }

    /**
     * Print an informal debug-only representation of object x.
     *
     * @param o the object
     * @return the buffer, in fluent style
     */
    public BasePrinter debugPrint(Object o) {
      if (o instanceof SkylarkValue) {
        ((SkylarkValue) o).debugPrint(this);
        return this;
      }

      return this.str(o);
    }

    /**
     * Print an informal representation of object x. Currently only differs from repr in the
     * behavior for strings and labels at top-level, that are returned as is rather than quoted.
     *
     * @param o the object
     * @return the buffer, in fluent style
     */
    public BasePrinter str(Object o) {
      if (o instanceof SkylarkValue) {
        ((SkylarkValue) o).str(this);
        return this;
      }

      if (o instanceof String) {
        return this.append((String) o);
      }
      return this.repr(o);
    }

    /**
     * Print an official representation of object x. For regular data structures, the value should
     * be parsable back into an equal data structure.
     *
     * @param o the string a representation of which to repr.
     * @return BasePrinter.
     */
    @Override
    public BasePrinter repr(Object o) {
      if (o == null) {
        // Java null is not a valid Skylark value, but sometimes printers are used on non-Skylark
        // values such as Locations or ASTs.
        this.append("null");

      } else if (o instanceof SkylarkPrintable) {
        ((SkylarkPrintable) o).repr(this);

      } else if (o instanceof String) {
        writeString((String) o);

      } else if (o instanceof Integer || o instanceof Double) {
        this.append(o.toString());

      } else if (Boolean.TRUE.equals(o)) {
        this.append("True");

      } else if (Boolean.FALSE.equals(o)) {
        this.append("False");

      } else if (o instanceof Map<?, ?>) {
        Map<?, ?> dict = (Map<?, ?>) o;
        this.printList(dict.entrySet(), "{", ", ", "}", null);

      } else if (o instanceof List<?>) {
        List<?> seq = (List<?>) o;
        this.printList(seq, false);

      } else if (o instanceof Map.Entry<?, ?>) {
        Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
        this.repr(entry.getKey());
        this.append(": ");
        this.repr(entry.getValue());
      } else if (o instanceof Class<?>) {
        this.append(EvalUtils.getDataTypeNameFromClass((Class<?>) o));

      } else if (o instanceof Node || o instanceof Location) {
        // AST node objects and locations are printed in tracebacks and error messages,
        // it's safe to print their toString representations
        this.append(o.toString());

      } else {
        // Other types of objects shouldn't be leaked to Skylark, but if happens, their
        // .toString method shouldn't be used because their return values are likely to contain
        // memory addresses or other nondeterministic information.
        this.append("<unknown object " + o.getClass().getName() + ">");
      }

      return this;
    }

    /**
     * Write a properly escaped Skylark representation of a string to a buffer.
     *
     * @param s the string a representation of which to repr.
     * @return this printer.
     */
    protected BasePrinter writeString(String s) {
      this.append('"');
      int len = s.length();
      for (int i = 0; i < len; i++) {
        char c = s.charAt(i);
        escapeCharacter(c);
      }
      return this.append('"');
    }

    private BasePrinter backslashChar(char c) {
      return this.append('\\').append(c);
    }

    private BasePrinter escapeCharacter(char c) {
      if (c == '"') {
        return backslashChar(c);
      }
      switch (c) {
        case '\\':
          return backslashChar('\\');
        case '\r':
          return backslashChar('r');
        case '\n':
          return backslashChar('n');
        case '\t':
          return backslashChar('t');
        default:
          if (c < 32) {
            //TODO(bazel-team): support \x escapes
            return this.append(String.format("\\x%02x", (int) c));
          }
          return this.append(c); // no need to support UTF-8
      } // endswitch
    }

    /**
     * Print a list of object representations
     *
     * @param list the list of objects to repr (each as with repr)
     * @param before a string to print before the list items, e.g. an opening bracket
     * @param separator a separator to print between items
     * @param after a string to print after the list items, e.g. a closing bracket
     * @param singletonTerminator null or a string to print after the list if it is a singleton The
     *     singleton case is notably relied upon in python syntax to distinguish a tuple of size one
     *     such as ("foo",) from a merely parenthesized object such as ("foo").
     * @return this printer.
     */
    @Override
    public BasePrinter printList(
        Iterable<?> list,
        String before,
        String separator,
        String after,
        @Nullable String singletonTerminator) {

      this.append(before);
      int len = appendListElements(list, separator);
      if (singletonTerminator != null && len == 1) {
        this.append(singletonTerminator);
      }
      return this.append(after);
    }

    /**
     * Appends the given elements to the specified {@link Appendable} and returns the number of
     * elements.
     */
    private int appendListElements(Iterable<?> list, String separator) {
      boolean printSeparator = false; // don't print the separator before the first element
      int len = 0;
      for (Object o : list) {
        if (printSeparator) {
          this.append(separator);
        }
        this.repr(o);
        printSeparator = true;
        len++;
      }
      return len;
    }

    /**
     * Print a Skylark list or tuple of object representations
     *
     * @param list the contents of the list or tuple
     * @param isTuple if true the list will be formatted with parentheses and with a trailing comma
     *     in case of one-element tuples. 'Soft' means that this limit may be exceeded because of
     *     formatting.
     * @return this printer.
     */
    @Override
    public BasePrinter printList(Iterable<?> list, boolean isTuple) {
      if (isTuple) {
        return this.printList(list, "(", ", ", ")", ",");
      } else {
        return this.printList(list, "[", ", ", "]", null);
      }
    }

    /**
     * Perform Python-style string formatting, similar to the {@code pattern % tuple} syntax.
     *
     * <p>The only supported placeholder patterns are
     * <ul>
     *   <li>{@code %s} (convert as if by {@code str()})
     *   <li>{@code %r} (convert as if by {@code repr()})
     *   <li>{@code %d} (convert an integer to its decimal representation)
     * </ul>
     * To encode a literal percent character, escape it as {@code %%}. It is an error to have a
     * non-escaped {@code %} at the end of the string or followed by any character not listed above.
     *
     * <p>If this printer has {@code simplifiedFormatStrings} set, only {@code %s} and {@code %%}
     * are permitted.
     *
     * @param pattern a format string that may contain placeholders
     * @param arguments an array containing arguments to substitute into the placeholders in order
     * @return the formatted string
     * @throws IllegalFormatException if {@code pattern} is not a valid format string, or if
     *     {@code arguments} mismatches the number or type of placeholders in {@code pattern}
     */
    @Override
    public BasePrinter format(String pattern, Object... arguments) {
      return this.formatWithList(pattern, Arrays.asList(arguments));
    }

    /**
     * Perform Python-style string formatting, similar to the {@code pattern % tuple} syntax.
     *
     * <p>Same as {@link #format(String, Object...)}, but with a list instead of variadic args.
     */
    @Override
    public BasePrinter formatWithList(String pattern, List<?> arguments) {
      // TODO(bazel-team): support formatting arguments, and more complex Python patterns.
      // N.B. MissingFormatWidthException is the only kind of IllegalFormatException
      // whose constructor can take and display arbitrary error message, hence its use below.

      int length = pattern.length();
      int argLength = arguments.size();
      int i = 0; // index of next character in pattern
      int a = 0; // index of next argument in arguments

      while (i < length) {
        int p = pattern.indexOf('%', i);
        if (p == -1) {
          Printer.append(buffer, pattern, i, length);
          break;
        }
        if (p > i) {
          Printer.append(buffer, pattern, i, p);
        }
        if (p == length - 1) {
          throw new MissingFormatWidthException(
              "incomplete format pattern ends with %: " + this.repr(pattern));
        }
        char directive = pattern.charAt(p + 1);
        i = p + 2;
        switch (directive) {
          case '%':
            this.append('%');
            continue;
          case 'd':
          case 'r':
          case 's':
            if (simplifiedFormatStrings && (directive != 's')) {
              throw new UnknownFormatConversionException(
                  "cannot use %" + directive + " substitution placeholder when "
                      + "simplifiedFormatStrings is set");
            }
            if (a >= argLength) {
              throw new MissingFormatWidthException(
                  "not enough arguments for format pattern "
                      + Printer.repr(pattern)
                      + ": "
                      + Printer.repr(Tuple.copyOf(arguments)));
            }
            Object argument = arguments.get(a++);
            switch (directive) {
              case 'd':
                if (argument instanceof Integer) {
                  this.append(argument.toString());
                  continue;
                } else {
                  throw new MissingFormatWidthException(
                      "invalid argument " + Printer.repr(argument) + " for format pattern %d");
                }
              case 'r':
                this.repr(argument);
                continue;
              case 's':
                this.str(argument);
                continue;
            }
            // fall through
          default:
            throw new MissingFormatWidthException(
                // The call to Printer.repr doesn't cause an infinite recursion because it's
                // only used to format a string properly
                String.format("unsupported format character \"%s\" at index %s in %s",
                    String.valueOf(directive), p + 1, Printer.repr(pattern)));
        }
      }
      if (a < argLength) {
        throw new MissingFormatWidthException(
            "not all arguments converted during string formatting");
      }
      return this;
    }

    @Override
    public BasePrinter append(char c) {
      Printer.append(buffer, c);
      return this;
    }

    @Override
    public BasePrinter append(CharSequence s) {
      Printer.append(buffer, s);
      return this;
    }

    BasePrinter append(CharSequence sequence, int start, int end) {
      return this.append(sequence.subSequence(start, end));
    }
  }

  /** A printer that breaks lines between the entries of lists, with proper indenting. */
  public static class PrettyPrinter extends BasePrinter {
    static final int BASE_INDENT = 4;
    private int indent;

    protected PrettyPrinter(Appendable buffer) {
      super(buffer);
      indent = 0;
    }

    @Override
    public BasePrinter printList(
        Iterable<?> list,
        String before,
        String untrimmedSeparator,
        String after,
        @Nullable String singletonTerminator) {

      // If the list is empty, do not split the presentation over
      // several lines.
      if (!list.iterator().hasNext()) {
        this.append(before + after);
        return this;
      }

      String separator = untrimmedSeparator.trim();

      this.append(before + "\n");
      indent += BASE_INDENT;
      boolean printSeparator = false; // don't print the separator before the first element
      int len = 0;
      for (Object o : list) {
        if (printSeparator) {
          this.append(separator + "\n");
        }
        this.append(Strings.repeat(" ", indent));
        this.repr(o);
        printSeparator = true;
        len++;
      }
      if (singletonTerminator != null && len == 1) {
        this.append(singletonTerminator);
      }
      this.append("\n");
      indent -= BASE_INDENT;
      this.append(Strings.repeat(" ", indent) + after);
      return this;
    }
  }
}
