/*
 * 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, Context.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);
        }
    }
}
