// 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.server.query;

import com.google.common.collect.Lists;
import com.google.inject.name.Named;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Rewrites a Predicate tree by applying rewrite rules.
 * <p>
 * Subclasses may document their rewrite rules by declaring public methods with
 * {@link Rewrite} annotations, such as:
 *
 * <pre>
 * &#064;Rewrite(&quot;A=(owner:*) B=(status:*)&quot;)
 * public Predicate r1_ownerStatus(@Named(&quot;A&quot;) OperatorPredicate owner,
 *     &#064;Named(&quot;B&quot;) OperatorPredicate status) {
 * }
 * </pre>
 * <p>
 * Rewrite methods are applied in order by declared name, so naming methods with
 * a numeric prefix to ensure a specific ordering (if required) is suggested.
 *
 * @param <T> type of object the predicate can evaluate in memory.
 */
public abstract class QueryRewriter<T> {
  /**
   * Defines the rewrite rules known by a QueryRewriter.
   *
   * This class is thread-safe and may be reused or cached.
   *
   * @param <T> type of object the predicates can evaluate in memory.
   * @param <R> type of the rewriter subclass.
   */
  public static class Definition<T, R extends QueryRewriter<T>> {
    private final List<RewriteRule<T>> rewriteRules;

    public Definition(Class<R> clazz, QueryBuilder<T> qb) {
      rewriteRules = Lists.newArrayList();

      Class<?> c = clazz;
      while (c != QueryRewriter.class) {
        Method[] declared = c.getDeclaredMethods();
        for (Method m : declared) {
          Rewrite rp = m.getAnnotation(Rewrite.class);
          if ((m.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT
              && (m.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC
              && rp != null) {
            rewriteRules.add(new MethodRewrite<T>(qb, rp.value(), m));
          }
        }
        c = c.getSuperclass();
      }
      Collections.sort(rewriteRules);
    }
  }

  private final List<RewriteRule<T>> rewriteRules;

  protected QueryRewriter(final Definition<T, ? extends QueryRewriter<T>> def) {
    this.rewriteRules = def.rewriteRules;
  }

  /** Combine the passed predicates into a single AND node. */
  public Predicate<T> and(Collection<? extends Predicate<T>> that) {
    return Predicate.and(that);
  }

  /** Combine the passed predicates into a single AND node. */
  public Predicate<T> and(@SuppressWarnings("unchecked") Predicate<T>... that) {
    return and(Arrays.asList(that));
  }

  /** Combine the passed predicates into a single OR node. */
  public Predicate<T> or(Collection<? extends Predicate<T>> that) {
    return Predicate.or(that);
  }

  /** Combine the passed predicates into a single OR node. */
  public Predicate<T> or(@SuppressWarnings("unchecked") Predicate<T>... that) {
    return or(Arrays.asList(that));
  }

  /** Invert the passed node. */
  public Predicate<T> not(Predicate<T> that) {
    return Predicate.not(that);
  }

  protected Predicate<T> preRewrite(Predicate<T> in) {
    return in;
  }

  /**
   * Apply rewrites to a graph until it stops changing.
   *
   * @param in the graph to rewrite.
   * @return the rewritten graph.
   */
  public final Predicate<T> rewrite(Predicate<T> in) {
    in = preRewrite(in);
    return rewriteImpl(in);
  }

  private Predicate<T> rewriteImpl(Predicate<T> in) {
    Predicate<T> old;
    do {
      old = in;
      in = rewriteOne(in);

      if (old.equals(in) && in.getChildCount() > 0) {
        List<Predicate<T>> n = new ArrayList<Predicate<T>>(in.getChildCount());
        for (Predicate<T> p : in.getChildren()) {
          n.add(rewriteImpl(p));
        }
        n = removeDuplicates(n);
        if (n.size() == 1 && (isAND(in) || isOR(in))) {
          in = n.get(0);
        } else {
          in = in.copy(n);
        }
      }

    } while (!old.equals(in));
    return replaceGenericNodes(in);
  }

  protected Predicate<T> replaceGenericNodes(final Predicate<T> in) {
    if (in instanceof NotPredicate) {
      return not(replaceGenericNodes(in.getChild(0)));

    } else if (in instanceof AndPredicate) {
      List<Predicate<T>> n = new ArrayList<Predicate<T>>(in.getChildCount());
      for (Predicate<T> c : in.getChildren()) {
        n.add(replaceGenericNodes(c));
      }
      return and(n);

    } else if (in instanceof OrPredicate) {
      List<Predicate<T>> n = new ArrayList<Predicate<T>>(in.getChildCount());
      for (Predicate<T> c : in.getChildren()) {
        n.add(replaceGenericNodes(c));
      }
      return or(n);

    } else {
      return in;
    }
  }

  private Predicate<T> rewriteOne(Predicate<T> input) {
    Predicate<T> best = null;
    for (RewriteRule<T> r : rewriteRules) {
      Predicate<T> n = r.rewrite(this, input);
      if (n == null) {
        continue;
      }

      if (!r.useBestCost()) {
        return n;
      }

      if (best == null || n.getCost() < best.getCost()) {
        best = n;
        continue;
      }
    }
    return best != null ? best : input;
  }

  private static class MatchResult<T> {
    private static final MatchResult<?> FAIL = new MatchResult<Object>(null);
    private static final MatchResult<?> OK = new MatchResult<Object>(null);

    @SuppressWarnings("unchecked")
    static <T> MatchResult<T> fail() {
      return (MatchResult<T>) FAIL;
    }

    @SuppressWarnings("unchecked")
    static <T> MatchResult<T> ok() {
      return (MatchResult<T>) OK;
    }

    final Predicate<T> extra;

    MatchResult(Predicate<T> extra) {
      this.extra = extra;
    }

    boolean success() {
      return this != FAIL;
    }
  }

  private MatchResult<T> match(final Map<String, Predicate<T>> outVars,
      final Predicate<T> pattern, final Predicate<T> actual) {
    if (pattern instanceof VariablePredicate) {
      final VariablePredicate<T> v = (VariablePredicate<T>) pattern;
      final MatchResult<T> r = match(outVars, v.getChild(0), actual);
      if (r.success()) {
        Predicate<T> old = outVars.get(v.getName());
        if (old == null) {
          outVars.put(v.getName(), actual);
          return r;
        } else if (old.equals(actual)) {
          return r;
        } else {
          return MatchResult.fail();
        }
      } else {
        return MatchResult.fail();
      }
    }

    if ((isAND(pattern) && isAND(actual)) //
        || (isOR(pattern) && isOR(actual)) //
        || (isNOT(pattern) && isNOT(actual)) //
    ) {
      // Order doesn't actually matter here. That does make our logic quite
      // a bit more complex as we need to consult each child at most once,
      // but in any order.
      //
      final LinkedList<Predicate<T>> have = dup(actual);
      final LinkedList<Predicate<T>> extra = new LinkedList<Predicate<T>>();
      for (final Predicate<T> pat : pattern.getChildren()) {
        boolean found = false;
        for (final Iterator<Predicate<T>> i = have.iterator(); i.hasNext();) {
          final MatchResult<T> r = match(outVars, pat, i.next());
          if (r.success()) {
            found = true;
            i.remove();
            if (r.extra != null) {
              extra.add(r.extra);
            }
            break;
          }
        }
        if (!found) {
          return MatchResult.fail();
        }
      }
      have.addAll(extra);
      switch (have.size()) {
        case 0:
          return MatchResult.ok();
        case 1:
          if (isNOT(actual)) {
            return new MatchResult<T>(actual.copy(have));
          }
          return new MatchResult<T>(have.get(0));
        default:
          return new MatchResult<T>(actual.copy(have));
      }

    } else if (pattern.equals(actual)) {
      return MatchResult.ok();

    } else if (pattern instanceof WildPatternPredicate
        && actual instanceof OperatorPredicate
        && ((OperatorPredicate<T>) pattern).getOperator().equals(
            ((OperatorPredicate<T>) actual).getOperator())) {
      return MatchResult.ok();

    } else {
      return MatchResult.fail();
    }
  }

  private static <T> LinkedList<Predicate<T>> dup(final Predicate<T> actual) {
    return new LinkedList<Predicate<T>>(actual.getChildren());
  }

  /**
   * Denotes a method which wants to replace a predicate expression.
   * <p>
   * This annotation must be applied to a public method which returns
   * {@link Predicate}. The arguments of the method should {@link Predicate}, or
   * any subclass of it. The annotation value is a query language string which
   * describes the subtree this rewrite applies to. Method arguments should be
   * named with a {@link Named} annotation, and the same names should be used in
   * the query.
   * <p>
   * For example:
   *
   * <pre>
   * &#064;Rewrite(&quot;A=(owner:*) B=(status:*)&quot;)
   * public Predicate ownerStatus(@Named(&quot;A&quot;) OperatorPredicate owner,
   *     &#064;Named(&quot;B&quot;) OperatorPredicate status) {
   * }
   * </pre>
   *
   * matches an AND Predicate with at least two children, one being an operator
   * predicate called "owner" and the other being an operator predicate called
   * "status". The variables in the query are matched by name against the
   * parameters.
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  protected @interface Rewrite {
    String value();
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  protected @interface NoCostComputation {
  }

  /** Applies a rewrite rule to a Predicate. */
  protected interface RewriteRule<T> extends Comparable<RewriteRule<T>> {
    /**
     * Apply a rewrite rule to the Predicate.
     *
     * @param input the input predicate to be tested, and possibly rewritten.
     * @return a rewritten form of the predicate if this rule matches with the
     *         tree {@code input} and has a rewrite for it; {@code null} if this
     *         rule does not want this predicate.
     */
    Predicate<T> rewrite(QueryRewriter<T> rewriter, Predicate<T> input);

    /** @return true if the best cost should be selected. */
    boolean useBestCost();
  }

  /** Implements the magic behind {@link Rewrite} annotations. */
  private static class MethodRewrite<T> implements RewriteRule<T> {
    private final Method method;
    private final Predicate<T> pattern;
    private final String[] argNames;
    private final Class<? extends Predicate<T>>[] argTypes;
    private final boolean useBestCost;

    @SuppressWarnings("unchecked")
    MethodRewrite(QueryBuilder<T> queryBuilder, String patternText, Method m) {
      method = m;
      useBestCost = m.getAnnotation(NoCostComputation.class) == null;

      Predicate<T> p;
      try {
        p = queryBuilder.parse(patternText);
      } catch (QueryParseException e) {
        throw new RuntimeException("Bad @Rewrite(\"" + patternText + "\")"
            + " on " + m.toGenericString() + " in " + m.getDeclaringClass()
            + ": " + e.getMessage(), e);
      }
      if (!Predicate.class.isAssignableFrom(m.getReturnType())) {
        throw new RuntimeException(m.toGenericString() + " in "
            + m.getDeclaringClass() + " must return " + Predicate.class);
      }

      pattern = p;
      argNames = new String[method.getParameterTypes().length];
      argTypes = new Class[argNames.length];
      for (int i = 0; i < argNames.length; i++) {
        Named name = null;
        for (Annotation a : method.getParameterAnnotations()[i]) {
          if (a instanceof Named) {
            name = (Named) a;
            break;
          }
        }
        if (name == null) {
          throw new RuntimeException("Argument " + (i + 1) + " of "
              + m.toGenericString() + " in " + m.getDeclaringClass()
              + " has no @Named annotation");
        }
        if (!Predicate.class.isAssignableFrom(method.getParameterTypes()[i])) {
          throw new RuntimeException("Argument " + (i + 1) + " of "
              + m.toGenericString() + " in " + m.getDeclaringClass()
              + " must be of type " + Predicate.class);
        }
        argNames[i] = name.value();
        argTypes[i] = (Class<Predicate<T>>) method.getParameterTypes()[i];
      }
    }

    @Override
    public boolean useBestCost() {
      return useBestCost;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Predicate<T> rewrite(QueryRewriter<T> rewriter,
        final Predicate<T> input) {
      final HashMap<String, Predicate<T>> args =
          new HashMap<String, Predicate<T>>();
      final MatchResult<T> res = rewriter.match(args, pattern, input);
      if (!res.success()) {
        return null;
      }

      final Predicate<T>[] argList = new Predicate[argNames.length];
      for (int i = 0; i < argList.length; i++) {
        argList[i] = args.get(argNames[i]);
        if (argList[i] == null) {
          final String a = "@Named(\"" + argNames[i] + "\")";
          throw error(new IllegalStateException("No value bound for " + a));
        }
        if (!argTypes[i].isInstance(argList[i])) {
          return null;
        }
      }

      final Predicate<T> rep;
      try {
        rep = (Predicate<T>) method.invoke(rewriter, (Object[]) argList);
      } catch (IllegalArgumentException e) {
        throw error(e);
      } catch (IllegalAccessException e) {
        throw error(e);
      } catch (InvocationTargetException e) {
        throw error(e.getCause());
      }

      if (rep instanceof RewritePredicate) {
        ((RewritePredicate<T>) rep).init(method.getName(), argList);
      }

      if (res.extra == null) {
        return rep;
      }

      Predicate<T> extra = removeDuplicates(res.extra);
      Predicate<T>[] newArgs = new Predicate[] {extra, rep};
      return input.copy(Arrays.asList(newArgs));
    }

    private IllegalArgumentException error(Throwable e) {
      final String msg = "Cannot apply " + method.getName();
      return new IllegalArgumentException(msg, e);
    }

    @Override
    public int compareTo(RewriteRule<T> in) {
      if (in instanceof MethodRewrite) {
        return method.getName().compareTo(
            ((MethodRewrite<T>) in).method.getName());
      }
      return 1;
    }
  }

  private static <T> Predicate<T> removeDuplicates(Predicate<T> in) {
    if (in.getChildCount() > 0) {
      List<Predicate<T>> n = removeDuplicates(in.getChildren());
      if (n.size() == 1 && (isAND(in) || isOR(in))) {
        in = n.get(0);
      } else {
        in = in.copy(n);
      }
    }
    return in;
  }

  private static <T> List<Predicate<T>> removeDuplicates(List<Predicate<T>> n) {
    List<Predicate<T>> r = new ArrayList<Predicate<T>>();
    for (Predicate<T> p : n) {
      if (!r.contains(p)) {
        r.add(p);
      }
    }
    return r;
  }

  private static <T> boolean isAND(final Predicate<T> p) {
    return p instanceof AndPredicate;
  }

  private static <T> boolean isOR(final Predicate<T> p) {
    return p instanceof OrPredicate;
  }

  private static <T> boolean isNOT(final Predicate<T> p) {
    return p instanceof NotPredicate;
  }
}
