/*
 * Copyright 2008 Google Inc.
 *
 * 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.gwt.dev.resource.impl;

import com.google.gwt.dev.resource.impl.PathPrefix.Judgement;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Combines the information conveyed about a set of path prefixes to quickly
 * answer questions regarding an entire set of path prefixes.
 * <p>
 * Is effectively immutable and should not be modified after initial use.
 */
public class PathPrefixSet {
  /*
   * (1) TODO(amitmanjhi): Improve the api of the PathPrefixSet so that with one
   * trie-traversal, it could be found out which resources rooted at a directory
   * are allowed?
   */

  private class TrieNode {
    // TODO(amitmanjhi): Consider the memory-speed tradeoff here
    private Map<String, TrieNode> children = Maps.create();
    private final String part;
    private List<PathPrefix> prefixes = Lists.newArrayList();
    private boolean hasPrefixes = false;

    public TrieNode(String part) {
      this.part = StringInterner.get().intern(part);
    }

    public TrieNode addChild(String part) {
      part = StringInterner.get().intern(part);
      TrieNode newChild = new TrieNode(part);
      assert !children.containsKey(part);
      children = Maps.put(children, part, newChild);
      return newChild;
    }

    public void addPathPrefix(PathPrefix prefix) {
      hasPrefixes = true;
      if (mergePathPrefixes) {
        if (prefixes.isEmpty()) {
          prefixes.add(prefix);
        } else {
          prefixes.get(0).merge(prefix);
        }
      } else {
        prefixes.add(prefix);
      }
    }

    public TrieNode findChild(String part) {
      return children.get(part);
    }

    public List<PathPrefix> getPathPrefixes() {
      return prefixes;
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();
      toString(sb, "");
      return sb.toString();
    }

    private void toString(StringBuilder sb, String indent) {
      if (sb.length() > 0) {
        sb.append('\n');
      }
      sb.append(indent);
      sb.append(' ');
      sb.append(part);
      for (TrieNode child : children.values()) {
        child.toString(sb, indent + "  ");
      }
    }
  }

  /**
   * Whether or not to merge prefixes that are added. Merged prefixes perform better during resource
   * scanning but at the cost of not being able to tell which module(s) are responsible for a
   * particular resource inclusion.
   */
  private boolean mergePathPrefixes = true;

  /**
   * List of all path prefixes in priority order.
   */
  private final List<PathPrefix> prefixes = new ArrayList<PathPrefix>();

  private final TrieNode rootTrieNode = new TrieNode("/");

  public PathPrefixSet() {
    this(true);
  }

  public PathPrefixSet(boolean mergePathPrefixes) {
    this.mergePathPrefixes = mergePathPrefixes;
  }

  /**
   * @param prefix the prefix to add
   * @return <code>true</code> if the prefix was not already in the set;
   *         otherwise, it merged with one having the same prefix, which has
   *         the effect of expanding the filter (the merge works as
   *         <code>union(includes - skips) - union(excludes)</code>)
   */
  public boolean add(PathPrefix prefix) {
    prefix.setPriority(prefixes.size());
    prefixes.add(prefix);

    String pathPrefix = prefix.getPrefix();

    /*
     * An empty prefix means we have no prefix requirement, but we do attach the
     * prefix to the root so that we can apply the filter.
     */
    if ("".equals(pathPrefix)) {
      rootTrieNode.addPathPrefix(prefix);
      return false;
    }

    // TODO(bruce): consider not using split for speed
    String[] parts = pathPrefix.split("/");
    TrieNode parentNode = rootTrieNode;
    boolean didAdd = false;
    for (String part : parts) {
      TrieNode childNode = parentNode.findChild(part);
      if (childNode != null) {
        // Follow existing branch.
        parentNode = childNode;
      } else {
        // Add a new branch.
        parentNode = parentNode.addChild(part);
        didAdd = true;
      }
    }
    assert (parentNode != null);
    parentNode.addPathPrefix(prefix);
    return didAdd;
  }

  public int getSize() {
    return prefixes.size();
  }

  /**
   * Determines whether or not a directory might have resources that could be
   * included. The primary purpose of this method is to allow
   * {@link ClassPathEntry} subclasses to avoid descending into directory
   * hierarchies that could not possibly contain resources that would be
   * included by {@link #includesResource(String)}
   *
   * @param dirPath must be a valid abstract directory name (must not be an
   *          empty string)
   * @return true if some PathPrefix allows the directory
   */
  public boolean includesDirectory(String dirPath) {
    assertValidAbstractDirectoryPathName(dirPath);

    /*
     * There are four cases:
     *
     * (1) The empty string was specified as a prefix, which causes everything
     * to be included.
     *
     * (2) As we walk the parts of dirPath, we see a path prefix attached to one
     * of the trie nodes we encounter. This means that there was a specified
     * prefix that this dirPath falls underneath, so it is included.
     *
     * (3) dirPath is longer than the trie, but we never encounter a path prefix
     * as we walk the trie. This indicates that this directory doesn't fall into
     * any of the specified prefixes.
     *
     * (4) dirPath is not longer than the trie and stays on the trie the whole
     * time, which means it is included (since at least some longer prefix
     * includes it).
     */

    if (rootTrieNode.hasPrefixes) {
      // Case (1).
      return true;
    }

    TrieNode parentNode = rootTrieNode;
    String[] parts = dirPath.split("/");
    for (String part : parts) {
      assert (!"".equals(part));
      TrieNode childNode = parentNode.findChild(part);
      if (childNode != null) {
        if (childNode.hasPrefixes) {
          // Case (2).
          return true;
        }

        // Haven't found a path prefix yet, so keep walking.
        parentNode = childNode;
      } else {
        // Case (3).
        return false;
      }
    }

    // Case (4).
    return true;
  }

  /**
   * Determines whether or not a given resource should be allowed by this path
   * prefix set and the corresponding filters.
   *
   * @param resourceAbstractPathName
   * @return matching <code>PathPrefix</code> if the resource matches some
   *         specified prefix and any associated filters don't exclude it.
   *         Otherwise, returns null. So it returns null if either no prefixes
   *         match or the most specific prefix excludes the resource.
   */
  public ResourceResolution includesResource(String resourceAbstractPathName) {
    String[] parts = resourceAbstractPathName.split("/");
    return includesResource(resourceAbstractPathName, parts);
  }

  /**
   * Dives down the package hierarchy looking for the most specific
   * package that applies to this resource. The filter of the most specific
   * package is the final determiner of inclusion/exclusion, such that more
   * specific subpackages can override the filter settings on less specific
   * superpackages.
   */
  public ResourceResolution includesResource(String resourceAbstractPathName,
      String[] parts) {
    assertValidAbstractResourcePathName(resourceAbstractPathName);

    ResourceResolution resourceResolution = new ResourceResolution();
    TrieNode currentNode = rootTrieNode;
    List<PathPrefix> mostSpecificPrefixes = rootTrieNode.getPathPrefixes();

    // Walk all but the last path part, which is assumed to be a file name.
    for (String part : parts) {
      assert (!"".equals(part));
      TrieNode childNode = currentNode.findChild(part);
      if (childNode == null) {
        break;
      }

      // We found a more specific node.
      if (childNode.hasPrefixes) {
        List<PathPrefix>  moreSpecificPrefixes = childNode.getPathPrefixes();
        // If PathPrefix->Module associations are accurate because PathPrefixes haven't been merged.
        if (!mergePathPrefixes) {
          // Record the module name of every PathPrefix that would allow this
          // resource. This enables detailed dependency validity checking.
          for (PathPrefix candidatePrefix : moreSpecificPrefixes) {
            if (candidatePrefix.getJudgement(
                resourceAbstractPathName).isInclude()) {
              resourceResolution.addSourceModuleName(
                  candidatePrefix.getModuleName());
            }
          }
        }

        mostSpecificPrefixes = moreSpecificPrefixes;
      }
      currentNode = childNode;
    }

    PathPrefix chiefPrefix = null;
    Judgement chiefJudgement = null;
    for (PathPrefix candidatePrefix : mostSpecificPrefixes) {
      Judgement judgement = candidatePrefix.getJudgement(
          resourceAbstractPathName);

      // EXCLUSION_EXCLUDE > FILTER_INCLUDE > IMPLICIT_EXCLUDE
      if (chiefJudgement == null ||
          judgement.getPriority() > chiefJudgement.getPriority()) {
        chiefPrefix = candidatePrefix;
        chiefJudgement = judgement;
      }
    }

    if (chiefPrefix == null || !chiefJudgement.isInclude()) {
      return null;
    }

    resourceResolution.setPathPrefix(chiefPrefix);
    return resourceResolution;
  }

  public boolean mergePathPrefixes() {
    return mergePathPrefixes;
  }

  @Override
  public String toString() {
    return rootTrieNode.toString();
  }

  public Collection<PathPrefix> values() {
    return Collections.unmodifiableCollection(prefixes);
  }

  private void assertValidAbstractDirectoryPathName(String name) {
    assert (name != null);
    assert (!name.startsWith("/"));
  }

  private void assertValidAbstractResourcePathName(String name) {
    assert (name != null);
    assert (!"".equals(name));
    assert (!name.startsWith("/") && !name.endsWith("/"));
  }
}
