package com.tomtom.espresso.test.actions;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;

import com.squareup.spoon.Spoon;

import org.hamcrest.Matcher;
import org.hamcrest.Matchers;

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.view.View;

import java.io.File;

/**
 * Class to take screenshots using Spoon library from an Espresso test
 * Original code from Gist: https://gist.github.com/edenman/7fdd32a4d59ccc01185b
 */
public final class SpoonScreenshotAction implements ViewAction {
    private final String mTag;
    private final String mTestClass;
    private final String mTestMethod;
    private static File sLastScreenshot;

    /**
     * Get the last captured screenshot file
     * @return Last screenshot file handler or null if there was no screenshot taken
     */
    public static File getLastScreenshot() {
        return sLastScreenshot;
    }

    /**
     * Initialize with information required to take a screenshot
     * @param tag Name of the screenshot to include in the file name
     * @param testClass Name of the class taking the screenshot (required by Spoon library)
     * @param testMethod Name of the method taking the screenshot
     */
    public SpoonScreenshotAction(final String tag, final String testClass, final String testMethod) {
        mTag = tag;
        mTestClass = testClass;
        mTestMethod = testMethod;
    }

    @Override
    public Matcher<View> getConstraints() {
        return Matchers.anything();
    }

    @Override
    public String getDescription() {
        return "Taking a screenshot using spoon.";
    }

    @Override
    public void perform(final UiController uiController, final View view) {
        sLastScreenshot = Spoon.screenshot(getActivity(view), mTag, mTestClass, mTestMethod);
    }

    /**
     * Get the activity from the context of the view
     * @param view View from which the activity will be inferred
     * @return Activity that contains the given view
     */
    private static Activity getActivity(final View view) {
        Context context = view.getContext();
        while (!(context instanceof Activity)) {
            if (context instanceof ContextWrapper) {
                context = ((ContextWrapper) context).getBaseContext();
            } else {
                throw new IllegalStateException("Got a context of class " + context.getClass() + " and I don't know how to get the Activity from it");
            }
        }
        return (Activity) context;
    }

    /**
     * Espresso action to be take a screenshot of the current activity
     * This must be called directly from the test method
     * @param tag Name of the screenshot to include in the file name
     */
    public static void perform(final String tag) {
        final StackTraceElement[] trace = Thread.currentThread().getStackTrace();
        final String testClass = trace[3].getClassName();
        final String testMethod = trace[3].getMethodName();
        onView(isRoot()).perform(new SpoonScreenshotAction(tag, testClass, testMethod));
    }
}