package org.checkerframework.checker.index.upperbound;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.value.ValueAnnotatedTypeFactory;
import org.checkerframework.common.value.ValueCheckerUtils;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.NumericalAdditionNode;
import org.checkerframework.dataflow.cfg.node.NumericalSubtractionNode;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.Unknown;
import org.checkerframework.framework.util.dependenttypes.DependentTypesError;
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.TreeUtils;

/**
 * An offset equation is 2 sets of Java expression strings, one set of added terms and one set of
 * subtracted terms, and a single integer constant. The Java expression strings have been
 * standardized and viewpoint-adapted.
 *
 * <p>An OffsetEquation is mutable.
 */
public class OffsetEquation {
  public static final OffsetEquation ZERO = createOffsetForInt(0);
  public static final OffsetEquation NEG_1 = createOffsetForInt(-1);
  public static final OffsetEquation ONE = createOffsetForInt(1);

  private final List<String> addedTerms;
  private final List<String> subtractedTerms;
  private int intValue = 0;
  private String error = null;

  private OffsetEquation() {
    addedTerms = new ArrayList<>(1);
    subtractedTerms = new ArrayList<>(1);
  }

  /**
   * Create a new OffsetEquation that is a copy of the given one.
   *
   * @param other the OffsetEquation to copy
   */
  protected OffsetEquation(OffsetEquation other) {
    this.addedTerms = new ArrayList<>(other.addedTerms);
    this.subtractedTerms = new ArrayList<>(other.subtractedTerms);
    this.error = other.error;
    this.intValue = other.intValue;
  }

  public boolean hasError() {
    return error != null;
  }

  public String getError() {
    return error;
  }

  @Override
  public boolean equals(@Nullable Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    OffsetEquation that = (OffsetEquation) o;

    if (intValue != that.intValue) {
      return false;
    }
    if (addedTerms.size() != that.addedTerms.size()
        || !addedTerms.containsAll(that.addedTerms)
        || !that.addedTerms.containsAll(addedTerms)) {
      return false;
    }
    if (subtractedTerms.size() != that.subtractedTerms.size()
        || !subtractedTerms.containsAll(that.subtractedTerms)
        || !that.subtractedTerms.containsAll(subtractedTerms)) {
      return false;
    }
    return error != null ? error.equals(that.error) : that.error == null;
  }

  @Override
  public int hashCode() {
    return Objects.hash(addedTerms, subtractedTerms, intValue, error);
  }

  @Override
  public String toString() {
    if (addedTerms.isEmpty() && subtractedTerms.isEmpty()) {
      return String.valueOf(intValue);
    }
    List<String> sortedAdds = new ArrayList<>(addedTerms);
    Collections.sort(sortedAdds);

    List<String> sortedSubs = new ArrayList<>(subtractedTerms);
    Collections.sort(sortedSubs);

    String adds = String.join(" + ", sortedAdds);
    String minus = String.join(" - ", sortedSubs);
    if (sortedSubs.size() == 1 && sortedAdds.isEmpty()) {
      minus = "-" + minus;
    } else if (!sortedSubs.isEmpty()) {
      minus = " - " + minus;
    }
    String terms = (adds + minus).trim();
    if (intValue != 0) {
      char op = intValue > 0 ? '+' : '-';
      if (terms.isEmpty()) {
        terms += intValue;
      } else {
        terms += " " + op + " " + Math.abs(intValue);
      }
    }
    return terms;
  }

  /**
   * Makes a copy of this offset and removes any added terms that are accesses to the length of the
   * listed sequences. If any terms were removed, then the copy is returned. Otherwise, null is
   * returned.
   *
   * @param sequences list of sequences (arrays or strings)
   * @return a copy of this equation with array.length and string.length() removed or null if no
   *     array.lengths or string.length() could be removed
   */
  public OffsetEquation removeSequenceLengths(List<String> sequences) {
    OffsetEquation copy = new OffsetEquation(this);
    boolean simplified = false;
    for (String sequence : sequences) {
      String arrayLen = sequence + ".length";
      if (addedTerms.contains(arrayLen)) {
        copy.addedTerms.remove(arrayLen);
        simplified = true;
      }
      String stringLen = sequence + ".length()";
      if (addedTerms.contains(stringLen)) {
        copy.addedTerms.remove(stringLen);
        simplified = true;
      }
    }
    return simplified ? copy : null;
  }
  /**
   * Adds or subtracts the other equation to a copy of this one.
   *
   * <p>If subtraction is specified, then every term in other is subtracted.
   *
   * @param op '-' for subtraction or '+' for addition
   * @param other equation to add or subtract
   * @return a copy of this equation +/- other
   */
  public OffsetEquation copyAdd(char op, OffsetEquation other) {
    assert op == '-' || op == '+';
    OffsetEquation copy = new OffsetEquation(this);
    if (op == '+') {
      copy.plus(other);
    } else {
      copy.minus(other);
    }
    return copy;
  }

  private void plus(OffsetEquation eq) {
    addInt(eq.intValue);
    for (String term : eq.addedTerms) {
      addTerm('+', term);
    }
    for (String term : eq.subtractedTerms) {
      addTerm('-', term);
    }
  }

  private void minus(OffsetEquation eq) {
    addInt(-1 * eq.intValue);
    for (String term : eq.addedTerms) {
      addTerm('-', term);
    }
    for (String term : eq.subtractedTerms) {
      addTerm('+', term);
    }
  }

  /**
   * Returns whether or not this equation is known to be less than or equal to the other equation.
   *
   * @param other equation
   * @return whether or not this equation is known to be less than or equal to the other equation
   */
  public boolean lessThanOrEqual(OffsetEquation other) {
    return (isInt() && other.isInt() && intValue <= other.getInt()) || this.equals(other);
  }

  /**
   * Returns true if this equation is a single int value.
   *
   * @return true if this equation is a single int value
   */
  public boolean isInt() {
    return addedTerms.isEmpty() && subtractedTerms.isEmpty();
  }

  /**
   * Returns the int value associated with this equation.
   *
   * <p>The equation may or may not have other terms. Use {@link #isInt()} to determine if the
   * equation is only this int value.
   *
   * @return the int value associated with this equation
   */
  public int getInt() {
    return intValue;
  }

  /**
   * Returns true if this equation is exactly -1.
   *
   * @return true if this equation is exactly -1
   */
  public boolean isNegOne() {
    return isInt() && getInt() == -1;
  }

  /**
   * Returns true if this equation non-negative.
   *
   * @return true if this equation non-negative
   */
  public boolean isNonNegative() {
    return isInt() && getInt() >= 0;
  }

  /**
   * Returns true if this equation is negative or zero.
   *
   * @return true if this equation is negative or zero
   */
  public boolean isNegativeOrZero() {
    return isInt() && getInt() <= 0;
  }

  /**
   * Adds the term to this equation. If string is an integer, then it is added or subtracted,
   * depending on operator, from the int value of this equation. Otherwise, the term is placed in
   * the added or subtracted terms set, depending on operator.
   *
   * @param operator '+' or '-'
   * @param term an int value or Java expression to add to this equation
   */
  private void addTerm(char operator, String term) {
    term = term.trim();
    if (operator == '-' && term.equals("2147483648")) {
      addInt(-2147483648);
      return;
    }
    if (isInt(term)) {
      int literal = parseInt(term);
      addInt(operator == '-' ? -1 * literal : literal);
      return;
    }
    if (operator == '-') {
      if (addedTerms.contains(term)) {
        addedTerms.remove(term);
      } else {
        subtractedTerms.add(term);
      }
    } else if (operator == '+') {
      if (subtractedTerms.contains(term)) {
        subtractedTerms.remove(term);
      } else {
        addedTerms.add(term);
      }
    } else {
      assert false;
    }
  }

  private void addInt(int value) {
    intValue += value;
  }

  /**
   * Returns the offset equation that is an int value or null if there isn't one.
   *
   * @param equationSet a set of offset equations
   * @return the offset equation that is an int value or null if there isn't one
   */
  public static OffsetEquation getIntOffsetEquation(Set<OffsetEquation> equationSet) {
    for (OffsetEquation eq : equationSet) {
      if (eq.isInt()) {
        return eq;
      }
    }
    return null;
  }
  /**
   * Creates an offset equation that is only the int value specified.
   *
   * @param value int value of the equation
   * @return an offset equation that is only the int value specified
   */
  public static OffsetEquation createOffsetForInt(int value) {
    OffsetEquation equation = new OffsetEquation();
    equation.intValue = value;
    return equation;
  }

  /**
   * Creates an offset equation from the expressionEquation. The expressionEquation may be several
   * Java expressions added or subtracted from each other. The expressionEquation may also start
   * with + or -. If the expressionEquation is the empty string, then the offset equation returned
   * is zero.
   *
   * @param expressionEquation a Java expression made up of sums and differences
   * @return an offset equation created from expressionEquation
   */
  public static OffsetEquation createOffsetFromJavaExpression(String expressionEquation) {
    expressionEquation = expressionEquation.trim();
    OffsetEquation equation = new OffsetEquation();
    if (expressionEquation.isEmpty()) {
      equation.addTerm('+', "0");
      return equation;
    }

    if (DependentTypesError.isExpressionError(expressionEquation)) {
      equation.error = expressionEquation;
      return equation;
    }
    if (indexOf(expressionEquation, '-', '+', 0) == -1) {
      equation.addTerm('+', expressionEquation);
      return equation;
    }

    int index = 0;
    while (index < expressionEquation.length()) {
      char operator = expressionEquation.charAt(index);
      if (operator == '-' || operator == '+') {
        index++;
      } else {
        operator = '+';
      }

      int endIndex = indexOf(expressionEquation, '-', '+', index);
      String subexpression;
      if (endIndex == -1) {
        endIndex = expressionEquation.length();
        subexpression = expressionEquation.substring(index);
      } else {
        subexpression = expressionEquation.substring(index, endIndex);
      }

      equation.addTerm(operator, subexpression);
      index = endIndex;
    }
    return equation;
  }

  /** A regular expression that matches an integer literal. */
  private static Pattern intPattern = Pattern.compile("[-+]?[0-9]+");

  /**
   * Returns true if the given string is an integer literal
   *
   * @param string a string
   * @return true if the given string is an integer literal
   */
  private static boolean isInt(String string) {
    return intPattern.matcher(string).matches();
  }

  private static int parseInt(String intLiteral) {
    if (intLiteral.isEmpty()) {
      return 0;
    }
    return Integer.valueOf(intLiteral);
  }

  /** Returns the first index of a or b in string, or -1 if neither char is in string. */
  private static int indexOf(String string, char a, char b, int index) {
    int aIndex = string.indexOf(a, index);
    int bIndex = string.indexOf(b, index);
    if (aIndex == -1) {
      return bIndex;
    } else if (bIndex == -1) {
      return aIndex;
    } else {
      return Math.min(aIndex, bIndex);
    }
  }

  /**
   * If node is an int value known at compile time, then the returned equation is just the int value
   * or if op is '-', the return equation is the negation of the int value.
   *
   * <p>Otherwise, null is returned.
   *
   * @param node the Node from which to create an offset equation
   * @param factory an AnnotationTypeFactory
   * @param op '+' or '-'
   * @return an offset equation from value of known or null if the value isn't known
   */
  public static OffsetEquation createOffsetFromNodesValue(
      Node node, ValueAnnotatedTypeFactory factory, char op) {
    assert op == '+' || op == '-';
    if (node.getTree() != null && TreeUtils.isExpressionTree(node.getTree())) {
      Long i = ValueCheckerUtils.getExactValue(node.getTree(), factory);
      if (i != null) {
        if (op == '-') {
          i = -i;
        }
        OffsetEquation eq = new OffsetEquation();
        eq.addInt(i.intValue());
        return eq;
      }
    }
    return null;
  }

  /**
   * Creates an offset equation from the Node.
   *
   * <p>If node is an addition or subtracted node, then this method is called recursively on the
   * left and right hand nodes and the two equations are added/subtracted to each other depending on
   * the value of op.
   *
   * <p>Otherwise the return equation is created by converting the node to a {@link
   * org.checkerframework.dataflow.expression.JavaExpression} and then added as a term to the
   * returned equation. If op is '-' then it is a subtracted term.
   *
   * @param node the Node from which to create an offset equation
   * @param factory an AnnotationTypeFactory
   * @param op '+' or '-'
   * @return an offset equation from the Node
   */
  public static OffsetEquation createOffsetFromNode(
      Node node, AnnotationProvider factory, char op) {
    assert op == '+' || op == '-';
    OffsetEquation eq = new OffsetEquation();
    createOffsetFromNode(node, factory, eq, op);
    return eq;
  }

  /**
   * Updates an offset equation from a Node.
   *
   * @param node the Node from which to create an offset equation
   * @param factory an AnnotationTypeFactory
   * @param eq an OffsetEquation to update
   * @param op '+' or '-'
   */
  private static void createOffsetFromNode(
      Node node, AnnotationProvider factory, OffsetEquation eq, char op) {
    JavaExpression je = JavaExpression.fromNode(node);
    if (je instanceof Unknown || je == null) {
      if (node instanceof NumericalAdditionNode) {
        createOffsetFromNode(((NumericalAdditionNode) node).getLeftOperand(), factory, eq, op);
        createOffsetFromNode(((NumericalAdditionNode) node).getRightOperand(), factory, eq, op);
      } else if (node instanceof NumericalSubtractionNode) {
        createOffsetFromNode(((NumericalSubtractionNode) node).getLeftOperand(), factory, eq, op);
        char other = op == '+' ? '-' : '+';
        createOffsetFromNode(
            ((NumericalSubtractionNode) node).getRightOperand(), factory, eq, other);
      } else {
        eq.error = node.toString();
      }
    } else {
      eq.addTerm(op, je.toString());
    }
  }
}
