package com.airbnb.lottie.model;

import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Defines which content to target.
 * The keypath can contain wildcards ('*') with match exactly 1 item.
 * or globstars ('**') which match 0 or more items. or KeyPath.COMPOSITION
 * to represent the root composition layer.
 * <p>
 * For example, if your content were arranged like this:
 * Gabriel (Shape Layer)
 * Body (Shape Group)
 * Left Hand (Shape)
 * Fill (Fill)
 * Transform (Transform)
 * ...
 * Brandon (Shape Layer)
 * Body (Shape Group)
 * Left Hand (Shape)
 * Fill (Fill)
 * Transform (Transform)
 * ...
 * <p>
 * <p>
 * You could:
 * Match Gabriel left hand fill:
 * new KeyPath("Gabriel", "Body", "Left Hand", "Fill");
 * Match Gabriel and Brandon's left hand fill:
 * new KeyPath("*", "Body", Left Hand", "Fill");
 * Match anything with the name Fill:
 * new KeyPath("**", "Fill");
 * Target the the root composition layer:
 * KeyPath.COMPOSITION
 * <p>
 * <p>
 * NOTE: Content that are part of merge paths or repeaters cannot currently be resolved with
 * a {@link KeyPath}. This may be fixed in the future.
 */
public class KeyPath {
  /**
   * A singleton KeyPath that targets on the root composition layer.
   * This is useful if you want to apply transformer to the animation as a whole.
   */
  public final static KeyPath COMPOSITION = new KeyPath("COMPOSITION");

  private final List<String> keys;
  @Nullable private KeyPathElement resolvedElement;

  public KeyPath(String... keys) {
    this.keys = Arrays.asList(keys);
  }

  /**
   * Copy constructor. Copies keys as well.
   */
  private KeyPath(KeyPath keyPath) {
    keys = new ArrayList<>(keyPath.keys);
    resolvedElement = keyPath.resolvedElement;
  }

  /**
   * Returns a new KeyPath with the key added.
   * This is used during keypath resolution. Children normally don't know about all of their parent
   * elements so this is used to keep track of the fully qualified keypath.
   * This returns a key keypath because during resolution, the full keypath element tree is walked
   * and if this modified the original copy, it would remain after popping back up the element tree.
   */
  @CheckResult
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public KeyPath addKey(String key) {
    KeyPath newKeyPath = new KeyPath(this);
    newKeyPath.keys.add(key);
    return newKeyPath;
  }

  /**
   * Return a new KeyPath with the element resolved to the specified {@link KeyPathElement}.
   */
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public KeyPath resolve(KeyPathElement element) {
    KeyPath keyPath = new KeyPath(this);
    keyPath.resolvedElement = element;
    return keyPath;
  }

  /**
   * Returns a {@link KeyPathElement} that this has been resolved to. KeyPaths get resolved with
   * resolveKeyPath on LottieDrawable or LottieAnimationView.
   */
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  @Nullable
  public KeyPathElement getResolvedElement() {
    return resolvedElement;
  }

  /**
   * Returns whether they key matches at the specified depth.
   */
  @SuppressWarnings("RedundantIfStatement")
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public boolean matches(String key, int depth) {
    if (isContainer(key)) {
      // This is an artificial layer we programatically create.
      return true;
    }
    if (depth >= keys.size()) {
      return false;
    }
    if (keys.get(depth).equals(key) ||
        keys.get(depth).equals("**") ||
        keys.get(depth).equals("*")) {
      return true;
    }
    return false;
  }

  /**
   * For a given key and depth, returns how much the depth should be incremented by when
   * resolving a keypath to children.
   * <p>
   * This can be 0 or 2 when there is a globstar and the next key either matches or doesn't match
   * the current key.
   */
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public int incrementDepthBy(String key, int depth) {
    if (isContainer(key)) {
      // If it's a container then we added programatically and it isn't a part of the keypath.
      return 0;
    }
    if (!keys.get(depth).equals("**")) {
      // If it's not a globstar then it is part of the keypath.
      return 1;
    }
    if (depth == keys.size() - 1) {
      // The last key is a globstar.
      return 0;
    }
    if (keys.get(depth + 1).equals(key)) {
      // We are a globstar and the next key is our current key so consume both.
      return 2;
    }
    return 0;
  }

  /**
   * Returns whether the key at specified depth is fully specific enough to match the full set of
   * keys in this keypath.
   */
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public boolean fullyResolvesTo(String key, int depth) {
    if (depth >= keys.size()) {
      return false;
    }
    boolean isLastDepth = depth == keys.size() - 1;
    String keyAtDepth = keys.get(depth);
    boolean isGlobstar = keyAtDepth.equals("**");

    if (!isGlobstar) {
      boolean matches = keyAtDepth.equals(key) || keyAtDepth.equals("*");
      return (isLastDepth || (depth == keys.size() - 2 && endsWithGlobstar())) && matches;
    }

    boolean isGlobstarButNextKeyMatches = !isLastDepth && keys.get(depth + 1).equals(key);
    if (isGlobstarButNextKeyMatches) {
      return depth == keys.size() - 2 ||
          (depth == keys.size() - 3 && endsWithGlobstar());
    }

    if (isLastDepth) {
      return true;
    }
    if (depth + 1 < keys.size() - 1) {
      // We are a globstar but there is more than 1 key after the globstar we we can't fully match.
      return false;
    }
    // Return whether the next key (which we now know is the last one) is the same as the current
    // key.
    return keys.get(depth + 1).equals(key);
  }

  /**
   * Returns whether the keypath resolution should propagate to children. Some keypaths resolve
   * to content other than leaf contents (such as a layer or content group transform) so sometimes
   * this will return false.
   */
  @SuppressWarnings("SimplifiableIfStatement")
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public boolean propagateToChildren(String key, int depth) {
    if ("__container".equals(key)) {
      return true;
    }
    return depth < keys.size() - 1 || keys.get(depth).equals("**");
  }

  /**
   * We artificially create some container groups (like a root ContentGroup for the entire animation
   * and for the contents of a ShapeLayer).
   */
  private boolean isContainer(String key) {
    return "__container".equals(key);
  }

  private boolean endsWithGlobstar() {
    return keys.get(keys.size() - 1).equals("**");
  }

  public String keysToString() {
    return keys.toString();
  }

  @Override public String toString() {
    return "KeyPath{" + "keys=" + keys + ",resolved=" + (resolvedElement != null) + '}';
  }
}
