// 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(final 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(final Constant c) {
    pattern = c.text;
    rawPattern = c.text;
    patternOps = Collections.<Format> singletonList(c);
    parameters = Collections.emptyList();
  }

  public ParameterizedString(final 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.substring(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(final 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(final Map<String, String> params) {
    final StringBuilder r = new StringBuilder();
    for (final Format f : patternOps) {
      f.format(r, params);
    }
    return r.toString();
  }

  public Builder replace(final String name, final 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(final String name, final 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(final 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(final 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);
  }
}
