// 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<Parameter>(4);
    final List<Format> ops = new ArrayList<Format>(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("{" + prs.size() + "}");
      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<String>(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<String, String>();

    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 static abstract 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<Function>(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 static abstract class Function {
    abstract String apply(String a);
  }

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

  private static Map<String, Function> initFunctions() {
    final HashMap<String, Function> m = new HashMap<String, Function>();
    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);
  }
}
