/*
 * Copyright 2012 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.validation.client.impl.metadata;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.validation.groups.Default;


/**
 * Contains all the information known about the inheritance information for validation groups.
 */
public class ValidationGroupsMetadata {

  /**
   * Builder for {@link ValidationGroupsMetadata}
   */
  public static class Builder {
    private final Map<Class<?>, Set<Class<?>>> inheritanceinheritanceMap;
    private final Map<Class<?>, List<Class<?>>> sequenceMap;

    private Builder() {
      inheritanceinheritanceMap = new HashMap<Class<?>, Set<Class<?>>>();
      sequenceMap = new HashMap<Class<?>, List<Class<?>>>();
      addGroup(Default.class);
    }

    /**
     * Adds a group to the inheritance map. May optionally include parents of the group.
     * @param group The validation group to add.
     * @param parents A list of validation groups which {@code group} extends. Can be empty if the
     * group contains no parents.
     */
    public Builder addGroup(Class<?> group, Class<?>... parents) {
      inheritanceinheritanceMap.put(group, new HashSet<Class<?>>(Arrays.asList(parents)));
      return this;
    }

    /**
     * Adds a group sequence to the sequence map.
     * @param groupSequence The class representing the sequence (annotated with &#064;GroupSequence)
     * @param sequenceGroups The groups in the sequence.
     */
    public Builder addSequence(Class<?> groupSequence, Class<?>... sequenceGroups) {
      sequenceMap.put(groupSequence, Arrays.asList(sequenceGroups));
      return this;
    }

    public ValidationGroupsMetadata build() {
      return new ValidationGroupsMetadata(inheritanceinheritanceMap, sequenceMap);
    }
  }

  /**
   * Creates a builder populated only with the {@link Default} group.
   */
  public static Builder builder() {
    return new Builder();
  }

  private final Map<Class<?>, Set<Class<?>>> inheritanceMapping;
  private final Map<Class<?>, List<Class<?>>> sequenceMapping;

  private ValidationGroupsMetadata(Map<Class<?>, Set<Class<?>>> inheritanceinheritanceMap,
      Map<Class<?>, List<Class<?>>> sequenceMap) {
    this.inheritanceMapping = Collections.unmodifiableMap(inheritanceinheritanceMap);
    this.sequenceMapping = Collections.unmodifiableMap(sequenceMap);
  }

  /**
   * Checks if a given group has been added to the inheritance map.
   */
  public boolean containsGroup(Class<?> group) {
    return inheritanceMapping.containsKey(group);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof ValidationGroupsMetadata)) {
      return false;
    }
    ValidationGroupsMetadata otherObj = (ValidationGroupsMetadata)other;
    return inheritanceMapping.equals(otherObj.inheritanceMapping)
        && sequenceMapping.equals(otherObj.sequenceMapping);
  }

  /**
   * Finds all of the validation groups extended by an intial set of groups.
   * @param baseGroups The initial set of groups to find parents of. These groups must have been
   * added to the inheritance map already.
   * @return A unified set of groups and their parents.
   * @throws IllegalArgumentException If an initial group has not been added to the map before
   * calling this method.
   */
  public Set<Class<?>> findAllExtendedGroups(Collection<Class<?>> baseGroups)
      throws IllegalArgumentException {
    Set<Class<?>> found = new HashSet<Class<?>>();
    Stack<Class<?>> remaining = new Stack<Class<?>>();
    // initialize
    for (Class<?> group : baseGroups) {
      if (!inheritanceMapping.containsKey(group)) {
        throw new IllegalArgumentException("The collection of groups contains a group which" +
            " was not added to the map. Be sure to call addGroup() for all groups first.");
      }
      remaining.push(group);
    }
    // traverse
    Class<?> current;
    Set<Class<?>> superInterfaces;
    while (!remaining.isEmpty()) {
      current = remaining.pop();
      found.add(current);
      superInterfaces = inheritanceMapping.get(current);
      for (Class<?> parent : superInterfaces) {
        if (!found.contains(parent)) {
          remaining.push(parent);
        }
      }
    }
    return found;
  }

  /**
   * Recursively gets all of the groups and sequence groups in the map (children and parents alike)
   * in one flat set.
   */
  public Set<Class<?>> getAllGroupsAndSequences() {
    Set<Class<?>> allGroups = new HashSet<Class<?>>();
    for (Map.Entry<Class<?>, Set<Class<?>>> entry : inheritanceMapping.entrySet()) {
      allGroups.add(entry.getKey());
      allGroups.addAll(entry.getValue());
    }
    allGroups.addAll(sequenceMapping.keySet());
    return allGroups;
  }

  /**
   * Returns all the known group sequence classes.
   */
  public Set<Class<?>> getGroupSequences() {
    return sequenceMapping.keySet();
  }

  /**
   * If the group has been added to the map then its parent groups (of one level above) are
   * retrieved. Otherwise null is returned.
   *
   * @see #containsGroup(Class)
   * @see #findAllExtendedGroups(Collection)
   */
  public Set<Class<?>> getParentsOfGroup(Class<?> group) {
    return inheritanceMapping.get(group);
  }

  /**
   * Returns all of the groups added to the map (but not their parents).
   */
  public Set<Class<?>> getRootGroups() {
    return inheritanceMapping.keySet();
  }

  /**
   * If the sequence class has been added to the map then the actual sequence list is retrieved.
   * Otherwise null is returned.
   */
  public List<Class<?>> getSequenceList(Class<?> sequence) {
    return sequenceMapping.get(sequence);
  }

  @Override
  public int hashCode() {
    int result = inheritanceMapping.hashCode();
    result = 31 * result + sequenceMapping.hashCode();
    return result;
  }

  /**
   * Checks if a group extends other groups (has parents).
   */
  public boolean hasParents(Class<?> group) {
    Set<Class<?>> possibleParents = getParentsOfGroup(group);
    return possibleParents != null && !possibleParents.isEmpty();
  }

  public boolean isInheritanceMapEmpty() {
    return inheritanceMapping.isEmpty();
  }

  /**
   * Checks if a given class is a group sequence map.
   */
  public boolean isSeqeuence(Class<?> sequence) {
    return sequenceMapping.containsKey(sequence);
  }

  public boolean isSequenceMapEmpty() {
    return sequenceMapping.isEmpty();
  }

  @Override
  public String toString() {
    return "ValidationGroupsMetaData{inheritanceMap=" + inheritanceMapping + ", " +
        "sequenceMap=" + sequenceMapping + "}";
  }
}
