// 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.common.data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/** Performs replacements on strings such as <code>Hello ${user}</code>. */
public class ParameterizedString {
  /** Obtain a string which has no parameters and always produces the value. */
  public static ParameterizedString asis(String constant) {
    return new ParameterizedString(new Constant(constant));
  }

  private final String pattern;
  private final String rawPattern;
  private final List<Format> patternOps;
  private final List<Parameter> parameters;

  protected ParameterizedString() {
    this(new Constant(""));
  }

  private ParameterizedString(Constant c) {
    pattern = c.text;
    rawPattern = c.text;
    patternOps = Collections.singletonList(c);
    parameters = Collections.emptyList();
  }

  public ParameterizedString(String pattern) {
    final StringBuilder raw = new StringBuilder();
    final List<Parameter> prs = new ArrayList<>(4);
    final List<Format> ops = new ArrayList<>(4);

    int i = 0;
    while (i < pattern.length()) {
      final int b = pattern.indexOf("${", i);
      if (b < 0) {
        break;
      }
      final int e = pattern.indexOf("}", b + 2);
      if (e < 0) {
        break;
      }

      raw.append(pattern, i, b);
      ops.add(new Constant(pattern.substring(i, b)));

      // "${parameter[.functions...]}" -> "parameter[.functions...]"
      final Parameter p = new Parameter(pattern.substring(b + 2, e));

      raw.append("{").append(prs.size()).append("}");
      prs.add(p);
      ops.add(p);

      i = e + 1;
    }
    if (i < pattern.length()) {
      raw.append(pattern.substring(i));
      ops.add(new Constant(pattern.substring(i)));
    }

    this.pattern = pattern;
    this.rawPattern = raw.toString();
    this.patternOps = Collections.unmodifiableList(ops);
    this.parameters = Collections.unmodifiableList(prs);
  }

  /** Get the original pattern given to the constructor. */
  public String getPattern() {
    return pattern;
  }

  /** Get the pattern with variables replaced with {0}, {1}, ... */
  public String getRawPattern() {
    return rawPattern;
  }

  /** Get the list of parameter names, ordered by appearance in the pattern. */
  public List<String> getParameterNames() {
    final ArrayList<String> r = new ArrayList<>(parameters.size());
    for (Parameter p : parameters) {
      r.add(p.name);
    }
    return Collections.unmodifiableList(r);
  }

  /** Convert a map of parameters into a value array for binding. */
  public String[] bind(Map<String, String> params) {
    final String[] r = new String[parameters.size()];
    for (int i = 0; i < r.length; i++) {
      final StringBuilder b = new StringBuilder();
      parameters.get(i).format(b, params);
      r[i] = b.toString();
    }
    return r;
  }

  /** Format this string by performing the variable replacements. */
  public String replace(Map<String, String> params) {
    final StringBuilder r = new StringBuilder();
    for (Format f : patternOps) {
      f.format(r, params);
    }
    return r.toString();
  }

  public Builder replace(String name, String value) {
    return new Builder().replace(name, value);
  }

  @Override
  public String toString() {
    return getPattern();
  }

  public final class Builder {
    private final Map<String, String> params = new HashMap<>();

    public Builder replace(String name, String value) {
      params.put(name, value);
      return this;
    }

    @Override
    public String toString() {
      return ParameterizedString.this.replace(params);
    }
  }

  private abstract static class Format {
    abstract void format(StringBuilder b, Map<String, String> p);
  }

  private static class Constant extends Format {
    private final String text;

    Constant(String text) {
      this.text = text;
    }

    @Override
    void format(StringBuilder b, Map<String, String> p) {
      b.append(text);
    }
  }

  private static class Parameter extends Format {
    private final String name;
    private final List<Function> functions;

    Parameter(String parameter) {
      // "parameter[.functions...]" -> (parameter, functions...)
      final List<String> names = Arrays.asList(parameter.split("\\."));
      final List<Function> functs = new ArrayList<>(names.size());

      if (names.isEmpty()) {
        name = "";
      } else {
        name = names.get(0);

        for (String fname : names.subList(1, names.size())) {
          final Function function = FUNCTIONS.get(fname);
          if (function != null) {
            functs.add(function);
          }
        }
      }

      functions = Collections.unmodifiableList(functs);
    }

    @Override
    void format(StringBuilder b, Map<String, String> p) {
      String v = p.get(name);
      if (v == null) {
        v = "";
      }
      for (Function function : functions) {
        v = function.apply(v);
      }
      b.append(v);
    }
  }

  private abstract static class Function {
    abstract String apply(String a);
  }

  private static final Map<String, Function> FUNCTIONS = initFunctions();

  private static Map<String, Function> initFunctions() {
    HashMap<String, Function> m = new HashMap<>();
    m.put(
        "toLowerCase",
        new Function() {
          @Override
          String apply(String a) {
            return a.toLowerCase(Locale.US);
          }
        });
    m.put(
        "toUpperCase",
        new Function() {
          @Override
          String apply(String a) {
            return a.toUpperCase(Locale.US);
          }
        });
    m.put(
        "localPart",
        new Function() {
          @Override
          String apply(String a) {
            int at = a.indexOf('@');
            return at < 0 ? a : a.substring(0, at);
          }
        });
    return Collections.unmodifiableMap(m);
  }
}
