/*
 * 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;

import com.google.gwt.validation.client.impl.metadata.ValidationGroupsMetadata;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.GroupDefinitionException;
import javax.validation.ValidationException;

/**
 * Helper class used to resolve groups and sequences into a single chain of groups which can then
 * be validated.
 * <p>
 * Modified from the Hibernate validator for use with GWT.
 */
public class GroupChainGenerator {
  private final ValidationGroupsMetadata validationGroupsMetadata;

  private final Map<Class<?>, List<Group>> resolvedSequences = new HashMap<Class<?>, List<Group>>();

  public GroupChainGenerator(ValidationGroupsMetadata validationGroupsMetadata) {
    this.validationGroupsMetadata = validationGroupsMetadata;
  }

  /**
   * Generates a chain of groups to be validated given the specified validation groups.
   *
   * @param groups The groups specified at the validation call.
   *
   * @return an instance of {@code GroupChain} defining the order in which validation has to occur.
   */
  public GroupChain getGroupChainFor(Collection<Class<?>> groups) {
    if (groups == null || groups.size() == 0) {
      throw new IllegalArgumentException("At least one group has to be specified.");
    }

    for (Class<?> clazz : groups) {
      if (!validationGroupsMetadata.containsGroup(clazz)
          && !validationGroupsMetadata.isSeqeuence(clazz)) {
        throw new ValidationException("The class " + clazz + " is not a valid group or sequence.");
      }
    }

    GroupChain chain = new GroupChain();
    for (Class<?> clazz : groups) {
      if (isGroupSequence(clazz)) {
        insertSequence(clazz, chain);
      }
      else {
        Group group = new Group(clazz);
        chain.insertGroup(group);
        insertInheritedGroups(clazz, chain);
      }
    }

    return chain;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder();
    sb.append("GroupChainGenerator");
    sb.append("{resolvedSequences=").append(resolvedSequences);
    sb.append('}');
    return sb.toString();
  }

  private void addGroups(List<Group> resolvedGroupSequence, List<Group> groups) {
    for (Group tmpGroup : groups) {
      if (resolvedGroupSequence.contains(tmpGroup)
          && resolvedGroupSequence.indexOf(tmpGroup) < resolvedGroupSequence.size() - 1) {
        throw new GroupDefinitionException("Unable to expand group sequence.");
      }
      resolvedGroupSequence.add(tmpGroup);
    }
  }

  private void addInheritedGroups(Group group, List<Group> expandedGroups) {
    Set<Class<?>> inheritedGroups = validationGroupsMetadata.getParentsOfGroup(group.getGroup());
    if (inheritedGroups != null) {
      for (Class<?> inheritedGroup : inheritedGroups) {
        if (isGroupSequence(inheritedGroup)) {
          throw new GroupDefinitionException("Sequence definitions are not allowed as composing " +
              "parts of a sequence.");
        }
        Group g = new Group(inheritedGroup, group.getSequence());
        expandedGroups.add(g);
        addInheritedGroups(g, expandedGroups);
      }
    }
  }

  private List<Group> expandInhertitedGroups(List<Group> sequence) {
    List<Group> expandedGroup = new ArrayList<Group>();
    for (Group group : sequence) {
      expandedGroup.add(group);
      addInheritedGroups(group, expandedGroup);
    }
    return expandedGroup;
  }

  /**
   * Recursively add inherited groups into the group chain.
   *
   * @param clazz The group interface
   * @param chain The group chain we are currently building.
   */
  private void insertInheritedGroups(Class<?> clazz, GroupChain chain) {
    for (Class<?> inheritedGroup : validationGroupsMetadata.getParentsOfGroup(clazz)) {
      Group group = new Group(inheritedGroup);
      chain.insertGroup(group);
      insertInheritedGroups(inheritedGroup, chain);
    }
  }

  private void insertSequence(Class<?> clazz, GroupChain chain) {
    List<Group> sequence;
    if (resolvedSequences.containsKey(clazz)) {
      sequence = resolvedSequences.get(clazz);
    } else {
      sequence = resolveSequence(clazz, new ArrayList<Class<?>>());
      // we expand the inherited groups only after we determined whether the sequence is expandable
      sequence = expandInhertitedGroups(sequence);
    }
    chain.insertSequence(sequence);
  }

  private boolean isGroupSequence(Class<?> clazz) {
    return validationGroupsMetadata.isSeqeuence(clazz);
  }

  private List<Group> resolveSequence(Class<?> group, List<Class<?>> processedSequences) {
    if (processedSequences.contains(group)) {
      throw new GroupDefinitionException("Cyclic dependency in groups definition");
    } else {
      processedSequences.add(group);
    }
    List<Group> resolvedGroupSequence = new ArrayList<Group>();
    List<Class<?>> sequenceList = validationGroupsMetadata.getSequenceList(group);
    for (Class<?> clazz : sequenceList ) {
      if (isGroupSequence(clazz)) {
        List<Group> tmpSequence = resolveSequence(clazz, processedSequences);
        addGroups(resolvedGroupSequence, tmpSequence);
      }
      else {
        List<Group> list = new ArrayList<Group>();
        list.add(new Group(clazz, group));
        addGroups(resolvedGroupSequence, list);
      }
    }
    resolvedSequences.put(group, resolvedGroupSequence);
    return resolvedGroupSequence;
  }
}
