/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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.android.test.runner.junit4;

import android.app.Instrumentation;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;

import com.android.test.InjectBundle;
import com.android.test.InjectContext;
import com.android.test.InjectInstrumentation;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.InitializationError;

import java.lang.reflect.Field;
import java.util.List;

/**
 * A specialized {@link BlockJUnit4ClassRunner} that can handle {@link InjectContext} and
 * {@link InjectInstrumentation}.
 */
class AndroidJUnit4ClassRunner extends BlockJUnit4ClassRunner {

    private static final String LOG_TAG = "AndroidJUnit4ClassRunner";
    private final Instrumentation mInstr;
    private final Bundle mBundle;

    @SuppressWarnings("serial")
    private static class InvalidInjectException extends Exception {
        InvalidInjectException(String message) {
            super(message);
        }
    }

    public AndroidJUnit4ClassRunner(Class<?> klass, Instrumentation instr, Bundle bundle)
            throws InitializationError {
        super(klass);
        mInstr = instr;
        mBundle = bundle;
    }

    @Override
    protected Object createTest() throws Exception {
        Object test = super.createTest();
        inject(test);
        return test;
    }

    @Override
    protected void collectInitializationErrors(List<Throwable> errors) {
        super.collectInitializationErrors(errors);

        validateInjectFields(errors);
    }

    private void validateInjectFields(List<Throwable> errors) {
        List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
                InjectInstrumentation.class);
        for (FrameworkField instrField : instrFields) {
            validateInjectField(errors, instrField, Instrumentation.class);
        }
        List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
                InjectContext.class);
        for (FrameworkField contextField : contextFields) {
            validateInjectField(errors, contextField, Context.class);
        }
        List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
                InjectBundle.class);
        for (FrameworkField bundleField : bundleFields) {
            validateInjectField(errors, bundleField, Bundle.class);
        }
    }

    private void validateInjectField(List<Throwable> errors, FrameworkField instrField,
            Class<?> expectedType) {
        if (!instrField.isPublic()) {
            errors.add(new InvalidInjectException(String.format(
                    "field %s in class %s has an InjectInstrumentation annotation," +
                    " but is not public", instrField.getName(), getTestClass().getName())));
        }
        if (!expectedType.isAssignableFrom(instrField.getType())) {
            errors.add(new InvalidInjectException(String.format(
                    "field %s in class %s has an InjectInstrumentation annotation," +
                    " but its not of %s type", instrField.getName(),
                    getTestClass().getName(), expectedType.getName())));
        }
    }

    private void inject(Object test) {
        List<FrameworkField> instrFields = getTestClass().getAnnotatedFields(
                InjectInstrumentation.class);
        for (FrameworkField instrField : instrFields) {
            setFieldValue(test, instrField.getField(), mInstr);
        }
        List<FrameworkField> contextFields = getTestClass().getAnnotatedFields(
                InjectContext.class);
        for (FrameworkField contextField : contextFields) {
            setFieldValue(test, contextField.getField(), mInstr.getTargetContext());
        }
        List<FrameworkField> bundleFields = getTestClass().getAnnotatedFields(
                InjectBundle.class);
        for (FrameworkField bundleField : bundleFields) {
            setFieldValue(test, bundleField.getField(), mBundle);
        }
    }

    private void setFieldValue(Object test, Field field, Object value) {
        try {
            field.set(test, value);
        } catch (IllegalArgumentException e) {
            Log.e(LOG_TAG, String.format(
                    "Failed to inject value for field %s in class %s", field.getName(),
                    test.getClass().getName()), e);
        } catch (IllegalAccessException e) {
            Log.e(LOG_TAG, String.format(
                    "Failed to inject value for field %s in class %s", field.getName(),
                    test.getClass().getName()), e);
        }
    }
}
