/*
 * Copyright 2009-2014 Marcelo Guimarães
 *
 * 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 org.atatec.trugger.validation.impl;

import org.atatec.trugger.element.Element;
import org.atatec.trugger.interception.Interception;
import org.atatec.trugger.interception.ValidationInterceptionHandler;
import org.atatec.trugger.util.factory.ComponentFactory;
import org.atatec.trugger.validation.ValidationEngine;
import org.atatec.trugger.validation.Validator;
import org.atatec.trugger.validation.ValidatorClass;
import org.atatec.trugger.validation.ValidatorFactory;

import java.lang.annotation.Annotation;

import static org.atatec.trugger.reflection.ParameterPredicates.assignableTo;
import static org.atatec.trugger.reflection.ParameterPredicates.type;
import static org.atatec.trugger.reflection.Reflection.invoke;

/**
 * Default validator factory implementation.
 *
 * @author Marcelo Guimarães
 * @since 5.1
 */
public class TruggerValidatorFactory implements ValidatorFactory {

  private ComponentFactory<ValidatorClass, Validator> createFactory() {
    ComponentFactory<ValidatorClass, Validator> factory =
        new ComponentFactory<>(ValidatorClass.class);
    factory.toCreate(
        (constructor, args) -> {
          Validator validator = invoke(constructor).withArgs(args);
          return Interception.intercept(Validator.class)
              .on(validator)
              .onCall(new ValidationInterceptionHandler(this)
                  .onInvalid(context -> true))
              .proxy();
        }
    );
    return factory;
  }

  @Override
  public Validator create(Annotation annotation) {
    ComponentFactory<ValidatorClass, Validator> factory = createFactory();
    return factory.create(annotation);
  }

  @Override
  public Validator create(Annotation annotation, Element element,
                          Object target, ValidationEngine engine) {
    ComponentFactory<ValidatorClass, Validator> factory = createFactory();
    factory.toConfigure(ComponentFactory.defaults().andThen(
        (context, an) -> {
          context.use(element).when(type(Element.class));
          context.use(engine).when(type(ValidationEngine.class));
          context.use(target).when(assignableTo(target.getClass())
              .or(type(Object.class)));
          context.use(an).when(type(Annotation.class));
          context.use(TruggerValidatorFactory.this)
              .when(type(ValidatorFactory.class));
        }
    ));
    return factory.create(annotation);
  }

}

@@ -918,180 +918,9 @@
 ion.
-ValidationEngine;%0Aimport org.atatec.trugger.validation.Validator;%0Aimport org.atatec.trugger.validation.ValidatorClass;%0Aimport org.atatec.trugger.validation.ValidatorFactory
+*
 ;%0A%0Ai
@@ -1573,24 +1573,169 @@
  args) -%3E %7B%0A
+          ArgumentsValidator argumentsValidator = new ArgumentsValidator(this);%0A          if (argumentsValidator.isValid(constructor, args)) %7B%0A  
           Va
@@ -1796,24 +1796,26 @@
 ;%0A          
+  
 return Inter
@@ -1849,16 +1849,18 @@
 .class)%0A
+  
         
@@ -1894,16 +1894,18 @@
         
+  
 .onCall(
@@ -1962,16 +1962,18 @@
         
+  
 .onInval
@@ -1993,16 +1993,18 @@
  true))%0A
+  
         
@@ -2015,24 +2015,59 @@
   .proxy();%0A
+          %7D%0A          return null;%0A
         %7D%0A  

validate constructor arguments too