package org.checkerframework.dataflow.constantpropagation;

import java.util.LinkedHashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Store;
import org.checkerframework.dataflow.cfg.node.IntegerLiteralNode;
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.visualize.CFGVisualizer;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.plumelib.util.CollectionsPlume;

/** A store that records information about constant values. */
public class ConstantPropagationStore implements Store<ConstantPropagationStore> {

  /** Information about variables gathered so far. */
  Map<Node, Constant> contents;

  /** Creates a new ConstantPropagationStore. */
  public ConstantPropagationStore() {
    contents = new LinkedHashMap<>();
  }

  protected ConstantPropagationStore(Map<Node, Constant> contents) {
    this.contents = contents;
  }

  public Constant getInformation(Node n) {
    if (contents.containsKey(n)) {
      return contents.get(n);
    }
    return new Constant(Constant.Type.TOP);
  }

  public void mergeInformation(Node n, Constant val) {
    Constant value;
    if (contents.containsKey(n)) {
      value = val.leastUpperBound(contents.get(n));
    } else {
      value = val;
    }
    // TODO: remove (only two nodes supported atm)
    assert n instanceof IntegerLiteralNode || n instanceof LocalVariableNode;
    contents.put(n, value);
  }

  public void setInformation(Node n, Constant val) {
    // TODO: remove (only two nodes supported atm)
    assert n instanceof IntegerLiteralNode || n instanceof LocalVariableNode;
    contents.put(n, val);
  }

  @Override
  public ConstantPropagationStore copy() {
    return new ConstantPropagationStore(new LinkedHashMap<>(contents));
  }

  @Override
  public ConstantPropagationStore leastUpperBound(ConstantPropagationStore other) {
    Map<Node, Constant> newContents = new LinkedHashMap<>(contents.size() + other.contents.size());

    // go through all of the information of the other class
    for (Map.Entry<Node, Constant> e : other.contents.entrySet()) {
      Node n = e.getKey();
      Constant otherVal = e.getValue();
      if (contents.containsKey(n)) {
        // merge if both contain information about a variable
        newContents.put(n, otherVal.leastUpperBound(contents.get(n)));
      } else {
        // add new information
        newContents.put(n, otherVal);
      }
    }

    for (Map.Entry<Node, Constant> e : contents.entrySet()) {
      Node n = e.getKey();
      Constant thisVal = e.getValue();
      if (!other.contents.containsKey(n)) {
        // add new information
        newContents.put(n, thisVal);
      }
    }

    return new ConstantPropagationStore(newContents);
  }

  @Override
  public ConstantPropagationStore widenedUpperBound(ConstantPropagationStore previous) {
    return leastUpperBound(previous);
  }

  @Override
  public boolean equals(@Nullable Object o) {
    if (o == null) {
      return false;
    }
    if (!(o instanceof ConstantPropagationStore)) {
      return false;
    }
    ConstantPropagationStore other = (ConstantPropagationStore) o;
    // go through all of the information of the other object
    for (Map.Entry<Node, Constant> e : other.contents.entrySet()) {
      Node n = e.getKey();
      Constant otherVal = e.getValue();
      if (otherVal.isBottom()) {
        continue; // no information
      }
      if (contents.containsKey(n)) {
        if (!otherVal.equals(contents.get(n))) {
          return false;
        }
      } else {
        return false;
      }
    }
    // go through all of the information of the this object
    for (Map.Entry<Node, Constant> e : contents.entrySet()) {
      Node n = e.getKey();
      Constant thisVal = e.getValue();
      if (thisVal.isBottom()) {
        continue; // no information
      }
      if (other.contents.containsKey(n)) {
        continue;
      } else {
        return false;
      }
    }
    return true;
  }

  @Override
  public int hashCode() {
    int s = 0;
    for (Map.Entry<Node, Constant> e : contents.entrySet()) {
      if (!e.getValue().isBottom()) {
        s += e.hashCode();
      }
    }
    return s;
  }

  @Override
  public String toString() {
    // only output local variable information
    Map<Node, Constant> contentsWithoutLocalVars =
        new LinkedHashMap<>(CollectionsPlume.mapCapacity(contents));
    for (Map.Entry<Node, Constant> e : contents.entrySet()) {
      if (e.getKey() instanceof LocalVariableNode) {
        contentsWithoutLocalVars.put(e.getKey(), e.getValue());
      }
    }
    return contentsWithoutLocalVars.toString();
  }

  @Override
  public boolean canAlias(JavaExpression a, JavaExpression b) {
    return true;
  }

  /**
   * {@inheritDoc}
   *
   * <p>{@code value} is {@code null} because {@link ConstantPropagationStore} doesn't support
   * visualization.
   */
  @Override
  @SuppressWarnings("nullness")
  public String visualize(CFGVisualizer<?, ConstantPropagationStore, ?> viz) {
    return viz.visualizeStoreKeyVal("constant propagation", null);
  }
}
