/*
 * Copyright 2010 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.BeanMetadata;
import com.google.gwt.validation.client.impl.metadata.MessageAndPath;
import com.google.gwt.validation.client.impl.metadata.ValidationGroupsMetadata;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintViolation;
import javax.validation.MessageInterpolator;
import javax.validation.ValidationException;
import javax.validation.groups.Default;

/**
 * Base methods for implementing a {@link GwtSpecificValidator}.
 * <p>
 * All methods that do not need to be generated go here.
 * 
 * @param <G> the type object to validate
 */
public abstract class AbstractGwtSpecificValidator<G> implements
    GwtSpecificValidator<G> {

  /**
   * Builds attributes one at a time.
   * <p>
   * Used to create a attribute map for annotations.
   */
  public static final class AttributeBuilder {
   private final HashMap<String, Object> tempMap = new HashMap<String, Object>();

    private AttributeBuilder() {
    }

    public Map<String, Object> build() {
      return Collections.unmodifiableMap(tempMap);
    }

    public AttributeBuilder put(String key, Object value) {
      tempMap.put(key, value);
      return this;
    }
  }

  public static AttributeBuilder attributeBuilder() {
    return new AttributeBuilder();
  }

  protected static Class<?>[] groupsToClasses(Group... groups) {
    int numGroups = groups.length;
    Class<?>[] array = new Class<?>[numGroups];
    for (int i = 0; i < numGroups; i++) {
      array[i] = groups[i].getGroup();
    }
    return array;
  }

  @Override
  public <T> Set<ConstraintViolation<T>> validate(
      GwtValidationContext<T> context,
      G object,
      Class<?>... groups) {
    context.addValidatedObject(object);
    try {
      GroupValidator classGroupValidator = new ClassGroupValidator(object);
      GroupChain groupChain = createGroupChainFromGroups(context, groups);
      BeanMetadata beanMetadata = getBeanMetadata();
      List<Class<?>> defaultGroupSeq = beanMetadata.getDefaultGroupSequence();
      if (beanMetadata.defaultGroupSequenceIsRedefined()) {
        // only need to check this on class-level validation
        groupChain.checkDefaultGroupSequenceIsExpandable(defaultGroupSeq);
      }
      return validateGroups(context, classGroupValidator, groupChain);
    } catch (IllegalArgumentException e) {
      throw e;
    } catch (ValidationException e) {
      throw e;
    } catch (Exception e) {
      throw new ValidationException("Error validating " + object.getClass(), e);
    }
  }

  @Override
  public <T> Set<ConstraintViolation<T>> validateProperty(
      GwtValidationContext<T> context,
      G object,
      String propertyName,
      Class<?>... groups) throws ValidationException {
    try {
      GroupValidator propertyGroupValidator = new PropertyGroupValidator(object, propertyName);
      GroupChain groupChain = createGroupChainFromGroups(context, groups);
      return validateGroups(context, propertyGroupValidator, groupChain);
    } catch (IllegalArgumentException e) {
      throw e;
    } catch (ValidationException e) {
      throw e;
    } catch (Exception e) {
      throw new ValidationException("Error validating property " + propertyName +
          " of " + object.getClass(), e);
    }
  }

  @Override
  public <T> Set<ConstraintViolation<T>> validateValue(
      GwtValidationContext<T> context,
      Class<G> beanType,
      String propertyName,
      Object value,
      Class<?>... groups) throws ValidationException {
    try {
      GroupValidator valueGroupValidator = new ValueGroupValidator(beanType, propertyName, value);
      GroupChain groupChain = createGroupChainFromGroups(context, groups);
      return validateGroups(context, valueGroupValidator, groupChain);
    } catch (IllegalArgumentException e) {
      throw e;
    } catch (ValidationException e) {
      throw e;
    } catch (Exception e) {
      throw new ValidationException("Error validating property " + propertyName +
          " with value " + value + " of " + beanType, e);
    }
  }

  protected List<Class<?>> addDefaultGroupWhenEmpty(List<Class<?>> groups) {
    if (groups.isEmpty()) {
      groups = new ArrayList<Class<?>>();
      groups.add(Default.class);
    }
    return groups;
  }

  protected <V, T, A extends Annotation> void addSingleViolation(
      GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations,
      G object, V value, ConstraintDescriptorImpl<A> constraintDescriptor) {
    ConstraintValidatorContextImpl<A, V> constraintValidatorContext =
      context.createConstraintValidatorContext(constraintDescriptor);
    addViolations(context, violations, object, value, constraintDescriptor,
        constraintValidatorContext);
  }

  /**
   * Perform the actual validation of a single {@link ConstraintValidator}.
   * <p>
   * As a side effect {@link ConstraintViolation}s may be added to
   * {@code violations}.
   * 
   * @return true if there was any constraint violations
   */
  protected <A extends Annotation, T, V> boolean validate(
      GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations,
      G object, V value, ConstraintValidator<A, ? super V> validator,
      ConstraintDescriptorImpl<A> constraintDescriptor, Class<?>... groups) {
    validator.initialize(constraintDescriptor.getAnnotation());
    ConstraintValidatorContextImpl<A, V> constraintValidatorContext =
        context.createConstraintValidatorContext(constraintDescriptor);

    List<Class<?>> groupsList = Arrays.asList(groups);
    ValidationGroupsMetadata validationGroupsMetadata =
        context.getValidator().getValidationGroupsMetadata();
    Set<Class<?>> constraintGroups = constraintDescriptor.getGroups();

    // check groups requested are in the set of constraint groups (including the implicit group)
    if (!containsAny(groupsList, constraintGroups)
        && !groupsList.contains(getConstraints(validationGroupsMetadata).getElementClass())) {
      return false;
    }

    if (!validator.isValid(value, constraintValidatorContext)) {
      addViolations(//
          context, //
          violations, //
          object, //
          value, //
          constraintDescriptor, //
          constraintValidatorContext);
      return true;
    }
    return false;
  }

  private <V, T, A extends Annotation> void addViolations(
      GwtValidationContext<T> context, Set<ConstraintViolation<T>> violations,
      G object, V value, ConstraintDescriptorImpl<A> constraintDescriptor,
      ConstraintValidatorContextImpl<A, V> constraintValidatorContext) {
    Set<MessageAndPath> mps = constraintValidatorContext.getMessageAndPaths();
    for (MessageAndPath messageAndPath : mps) {
      ConstraintViolation<T> violation = createConstraintViolation(//
          context, //
          object, //
          value, //
          constraintDescriptor, //
          messageAndPath);
      violations.add(violation);
    }
  }

  private <T> boolean containsAny(Collection<T> left, Collection<T> right) {
    for (T t : left) {
      if (right.contains(t)) {
        return true;
      }
    }
    return false;
  }

  private <T, V, A extends Annotation> ConstraintViolation<T> createConstraintViolation(
      GwtValidationContext<T> context, G object, V value,
      ConstraintDescriptorImpl<A> constraintDescriptor,
      MessageAndPath messageAndPath) {
    MessageInterpolator messageInterpolator = context.getMessageInterpolator();
    com.google.gwt.validation.client.impl.MessageInterpolatorContextImpl messageContext = new MessageInterpolatorContextImpl(
        constraintDescriptor, value);
    String message = messageInterpolator.interpolate(
        messageAndPath.getMessage(), messageContext);
    ConstraintViolation<T> violation = ConstraintViolationImpl.<T> builder() //
        .setConstraintDescriptor(constraintDescriptor) //
        .setInvalidValue(value) //
        .setLeafBean(object) //
        .setMessage(message) //
        .setMessageTemplate(messageAndPath.getMessage()) //
        .setPropertyPath(messageAndPath.getPath()) //
        .setRootBean(context.getRootBean()) //
        .setRootBeanClass(context.getRootBeanClass()) //
        .setElementType(constraintDescriptor.getElementType()) //
        .build();
    return violation;
  }

  private <T> GroupChain createGroupChainFromGroups(GwtValidationContext<T> context, Class<?>... groups) {
    List<Class<?>> groupsList = addDefaultGroupWhenEmpty(Arrays.asList(groups));
    ValidationGroupsMetadata validationGroupsMetadata =
        context.getValidator().getValidationGroupsMetadata();
    return new GroupChainGenerator(validationGroupsMetadata).getGroupChainFor(groupsList);
  }

  /**
   * Performs the top-level validation using a helper {@link GroupValidator}. This takes
   * group sequencing and Default group overriding into account.
   */
  private <T> Set<ConstraintViolation<T>> validateGroups(
      GwtValidationContext<T> context,
      GroupValidator groupValidator,
      GroupChain groupChain) {

    Set<ConstraintViolation<T>> violations = new HashSet<ConstraintViolation<T>>();

    Collection<Group> allGroups = groupChain.getAllGroups();
    Group[] allGroupsArray = allGroups.toArray(new Group[allGroups.size()]);
    groupValidator.validateGroups(context, violations, allGroupsArray);

    // handle sequences
    Iterator<List<Group>> sequenceIterator = groupChain.getSequenceIterator();
    while (sequenceIterator.hasNext()) {
      List<Group> sequence = sequenceIterator.next();
      for (Group group : sequence) {
        int numberOfViolations = violations.size();
        groupValidator.validateGroups(context, violations, group);
        if (violations.size() > numberOfViolations) {
          // stop processing when an error occurs
          break;
        }
      }
    }
    return violations;
  }

  private class ClassGroupValidator implements GroupValidator {
    private final G object;

    public ClassGroupValidator(G object) {
      this.object = object;
    }

    @Override
    public <T> void validateGroups(GwtValidationContext<T> context,
        Set<ConstraintViolation<T>> violations, Group... groups) {
      expandDefaultAndValidateClassGroups(context, object, violations, groups);
    }
  }

  private class PropertyGroupValidator implements GroupValidator {
    private final G object;
    private final String propertyName;

    public PropertyGroupValidator(G object, String propertyName) {
      this.object = object;
      this.propertyName = propertyName;
    }

    @Override
    public <T> void validateGroups(GwtValidationContext<T> context,
        Set<ConstraintViolation<T>> violations, Group... groups) {
      expandDefaultAndValidatePropertyGroups(context, object, propertyName, violations, groups);
    }
  }

  private class ValueGroupValidator implements GroupValidator {
    private final Class<G> beanType;
    private final String propertyName;
    private final Object value;

    public ValueGroupValidator(Class<G> beanType, String propertyName, Object value) {
      this.beanType = beanType;
      this.propertyName = propertyName;
      this.value = value;
    }

    @Override
    public <T> void validateGroups(GwtValidationContext<T> context,
        Set<ConstraintViolation<T>> violations, Group... groups) {
      expandDefaultAndValidateValueGroups(context, beanType, propertyName, value, violations, //
          groups);
    }
  }
}
