// 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.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();
          }
        });
    m.put(
        "toUpperCase",
        new Function() {
          @Override
          String apply(String a) {
            return a.toUpperCase();
          }
        });
    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);
  }
}
