/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.commons.proxy2.stub;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.reflect.TypeUtils;
import org.apache.commons.proxy2.Interceptor;
import org.apache.commons.proxy2.ObjectProvider;
import org.apache.commons.proxy2.interceptor.InterceptorUtils;
import org.apache.commons.proxy2.interceptor.matcher.ArgumentMatcher;
import org.apache.commons.proxy2.interceptor.matcher.argument.ArgumentMatcherUtils;

public abstract class BaseTrainer<S extends BaseTrainer<S, T>, T>
{
    //******************************************************************************************************************
    // Fields
    //******************************************************************************************************************
    public final Class<T> traineeType;

    //******************************************************************************************************************
    // Constructors
    //******************************************************************************************************************

    /**
     * Create a new {@link BaseTrainer} instance. This constructor should only be called by classes that explicitly
     * assign the T parameter in the class definition. This should include basically any runtime-usable class.
     */
    protected BaseTrainer()
    {
        this(null);
    }

    protected BaseTrainer(Class<T> traineeType)
    {
        super();
        if (traineeType != null)
        {
            this.traineeType = traineeType;
            return;
        }
        @SuppressWarnings("unchecked") // T is this class's second type parameter; thus the raw type is Class<T>
        final Class<T> resolvedVariable = (Class<T>) TypeUtils.getRawType(BaseTrainer.class.getTypeParameters()[1],
                getClass());
        Validate.isTrue(resolvedVariable != null, "Trainee type was not specified and could not be calculated for %s",
                getClass());
        this.traineeType = resolvedVariable;
    }

    //******************************************************************************************************************
    // Abstract Methods
    //******************************************************************************************************************

    protected abstract void train(T trainee);

    //******************************************************************************************************************
    // Other Methods
    //******************************************************************************************************************

    protected <R> R any(Class<R> type)
    {
        return argThat(ArgumentMatcherUtils.<R> any());
    }

    protected <R> R eq(R value)
    {
        return argThat(ArgumentMatcherUtils.eq(value));
    }

    protected <R> R isInstance(Class<R> type)
    {
        return argThat(ArgumentMatcherUtils.<R> isA(type));
    }

    protected <R> R argThat(ArgumentMatcher<R> matcher)
    {
        trainingContext().record(matcher);
        return null;
    }

    protected void thenThrow(Exception e)
    {
        trainingContext().then(InterceptorUtils.throwing(e));
    }

    protected void thenThrow(ObjectProvider<? extends Exception> provider)
    {
        trainingContext().then(InterceptorUtils.throwing(provider));
    }

    protected TrainingContext trainingContext()
    {
        return TrainingContext.current();
    }

    public <R> WhenObject<R> when(R expression)
    {
        return new WhenObject<R>();
    }

    public WhenClass when(Class<?> expression)
    {
        return new WhenClass();
    }

    public WhenByteArray when(byte[] expression)
    {
        return new WhenByteArray();
    }

    public WhenBooleanArray when(boolean[] expression)
    {
        return new WhenBooleanArray();
    }

    public WhenIntArray when(int[] expression)
    {
        return new WhenIntArray();
    }

    public WhenShortArray when(short[] expresssion)
    {
        return new WhenShortArray();
    }

    public WhenLongArray when(long[] expression)
    {
        return new WhenLongArray();
    }

    public WhenFloatArray when(float[] expression)
    {
        return new WhenFloatArray();
    }

    public WhenDoubleArray when(double[] expression)
    {
        return new WhenDoubleArray();
    }

    public <R> WhenObjectArray<R> when(R[] expression)
    {
        @SuppressWarnings("unchecked") // we can reasonably say that the component type of an R[] is Class<? extends R>:
        final Class<? extends R> componentType = (Class<? extends R>) expression.getClass().getComponentType();
        return new WhenObjectArray<R>(componentType);
    }

    public WhenCharArray when(char[] expression)
    {
        return new WhenCharArray();
    }

    protected S self()
    {
        @SuppressWarnings("unchecked") // S is our "self" type parameter
        final S self = (S) this;
        return self;
    }

    //******************************************************************************************************************
    // Inner Classes
    //******************************************************************************************************************

    protected abstract class BaseWhen<R>
    {
        public S thenThrow(Exception e)
        {
            return then(InterceptorUtils.throwing(e));
        }

        public S thenThrow(ObjectProvider<? extends Exception> provider)
        {
            return then(InterceptorUtils.throwing(provider));
        }

        public S thenAnswer(ObjectProvider<? extends R> provider)
        {
            return then(InterceptorUtils.provider(provider));
        }

        public S then(Interceptor interceptor)
        {
            trainingContext().then(interceptor);
            return self();
        }
    }

    protected class WhenBooleanArray extends BaseWhen<boolean[]>
    {
        public S thenReturn(boolean... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenByteArray extends BaseWhen<byte[]>
    {
        public S thenReturn(byte... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenCharArray extends BaseWhen<char[]>
    {
        public S thenReturn(char... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenDoubleArray extends BaseWhen<double[]>
    {
        public S thenReturn(double... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenFloatArray extends BaseWhen<float[]>
    {
        public S thenReturn(float... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenIntArray extends BaseWhen<int[]>
    {
        public S thenReturn(int... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenLongArray extends BaseWhen<long[]>
    {
        public S thenReturn(long... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }

    protected class WhenObject<R> extends BaseWhen<R>
    {
        public S thenReturn(R value)
        {
            trainingContext().then(InterceptorUtils.constant(value));
            return self();
        }

        public S thenStub(BaseTrainer<?, R> trainer)
        {
            final R trainee = trainingContext().push(trainer.traineeType);
            trainer.train(trainee);
            trainingContext().then(InterceptorUtils.constant(trainingContext().pop()));
            return self();
        }
    }

    /**
     * Intermediate result of a when(Class) call. Provided because it is such a common case to have a mismatch between a
     * declared Class<?> return type and the bound parameter of a class literal.
     */
    protected class WhenClass extends BaseWhen<Class<?>>
    {
        public S thenReturn(Class<?> value)
        {
            trainingContext().then(InterceptorUtils.constant(value));
            return self();
        }
    }

    protected class WhenObjectArray<R> extends BaseWhen<R[]>
    {
        protected final Class<? extends R> componentType;

        protected WhenObjectArray(Class<? extends R> componentType)
        {
            this.componentType = componentType;
        }

        public S thenReturn(R... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }

        public StubArrayBuilder<R> thenBuildArray()
        {
            return new StubArrayBuilder<R>(componentType);
        }
    }

    protected class StubArrayBuilder<R>
    {
        protected final List<R> elements = new ArrayList<R>();
        protected final Class<? extends R> componentType;

        protected StubArrayBuilder(Class<? extends R> componentType)
        {
            this.componentType = componentType;
        }

        public StubArrayBuilder<R> addElement(BaseTrainer<?, R> trainer)
        {
            final R trainee = trainingContext().push(trainer.traineeType);
            trainer.train(trainee);
            elements.add(trainingContext().<R> pop());
            return this;
        }

        public S build()
        {
            @SuppressWarnings("unchecked") // an array of component type ? extends R is assignable to R[]:
            final R[] array = elements.toArray((R[]) Array.newInstance(componentType, elements.size()));
            trainingContext().then(InterceptorUtils.constant(array));
            return self();
        }
    }

    protected class WhenShortArray extends BaseWhen<short[]>
    {
        public S thenReturn(short... values)
        {
            trainingContext().then(InterceptorUtils.constant(ArrayUtils.clone(values)));
            return self();
        }
    }
}
