/*
 * 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.util.Log;

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;

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

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

    @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);
        }
    }

    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());
        }
    }

    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);
        }
    }
}
