/*
 * Copyright (C) 2014 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 android.uirendering.cts.testinfrastructure;

import android.annotation.Nullable;
import android.app.Activity;
import android.app.Instrumentation;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.renderscript.Allocation;
import android.renderscript.RenderScript;
import android.support.test.rule.ActivityTestRule;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
import android.uirendering.cts.differencevisualizers.DifferenceVisualizer;
import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
import android.uirendering.cts.util.BitmapDumper;
import android.util.Log;

import android.support.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.assertTrue;

/**
 * This class contains the basis for the graphics hardware test classes. Contained within this class
 * are several methods that help with the execution of tests, and should be extended to gain the
 * functionality built in.
 */
public abstract class ActivityTestBase {
    public static final String TAG = "ActivityTestBase";
    public static final boolean DEBUG = false;
    public static final boolean USE_RS = false;

    //The minimum height and width of a device
    public static final int TEST_WIDTH = 90;
    public static final int TEST_HEIGHT = 90;

    public static final int MAX_SCREEN_SHOTS = 100;

    private int[] mHardwareArray = new int[TEST_HEIGHT * TEST_WIDTH];
    private int[] mSoftwareArray = new int[TEST_HEIGHT * TEST_WIDTH];
    private DifferenceVisualizer mDifferenceVisualizer;
    private RenderScript mRenderScript;
    private TestCaseBuilder mTestCaseBuilder;

    @Rule
    public ActivityTestRule<DrawActivity> mActivityRule = new ActivityTestRule<>(
            DrawActivity.class);

    @Rule
    public TestName name = new TestName();

    /**
     * The default constructor creates the package name and sets the DrawActivity as the class that
     * we would use.
     */
    public ActivityTestBase() {
        mDifferenceVisualizer = new PassFailVisualizer();

        // Create a location for the files to be held, if it doesn't exist already
        BitmapDumper.createSubDirectory(this.getClass().getSimpleName());

        // If we have a test currently, let's remove the older files if they exist
        if (getName() != null) {
            BitmapDumper.deleteFileInClassFolder(this.getClass().getSimpleName(), getName());
        }
    }

    protected DrawActivity getActivity() {
        return mActivityRule.getActivity();
    }

    protected String getName() {
        return name.getMethodName();
    }

    protected Instrumentation getInstrumentation() {
        return InstrumentationRegistry.getInstrumentation();
    }

    @Before
    public void setUp() {
        mDifferenceVisualizer = new PassFailVisualizer();
        if (USE_RS) {
            mRenderScript = RenderScript.create(getActivity().getApplicationContext());
        }
    }

    @After
    public void tearDown() {
        if (mTestCaseBuilder != null) {
            List<TestCase> testCases = mTestCaseBuilder.getTestCases();

            if (testCases.size() == 0) {
                throw new IllegalStateException("Must have at least one test case");
            }

            for (TestCase testCase : testCases) {
                if (!testCase.wasTestRan) {
                    Log.w(TAG, getName() + " not all of the tests ran");
                    break;
                }
            }
            mTestCaseBuilder = null;
        }
    }

    public Bitmap takeScreenshot(Point testOffset) {
        getInstrumentation().waitForIdleSync();
        Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
        return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
    }

    /**
     * Sets the current DifferenceVisualizer for use in current test.
     */
    public void setDifferenceVisualizer(DifferenceVisualizer differenceVisualizer) {
        mDifferenceVisualizer = differenceVisualizer;
    }

    /**
     * Used to execute a specific part of a test and get the resultant bitmap
     */
    protected Bitmap captureRenderSpec(TestCase testCase) {
        Point testOffset = getActivity().enqueueRenderSpecAndWait(
                testCase.layoutID, testCase.canvasClient,
                null, testCase.viewInitializer, testCase.useHardware);
        testCase.wasTestRan = true;
        return takeScreenshot(testOffset);
    }

    /**
     * Compares the two bitmaps saved using the given test. If they fail, the files are saved using
     * the test name.
     */
    protected void assertBitmapsAreSimilar(Bitmap bitmap1, Bitmap bitmap2,
            BitmapComparer comparer, String debugMessage) {
        boolean success;

        if (USE_RS && comparer.supportsRenderScript()) {
            Allocation idealAllocation = Allocation.createFromBitmap(mRenderScript, bitmap1,
                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
            Allocation givenAllocation = Allocation.createFromBitmap(mRenderScript, bitmap2,
                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
            success = comparer.verifySameRS(getActivity().getResources(), idealAllocation,
                    givenAllocation, 0, TEST_WIDTH, TEST_WIDTH, TEST_HEIGHT, mRenderScript);
        } else {
            bitmap1.getPixels(mSoftwareArray, 0, TEST_WIDTH, 0, 0, TEST_WIDTH, TEST_HEIGHT);
            bitmap2.getPixels(mHardwareArray, 0, TEST_WIDTH, 0, 0, TEST_WIDTH, TEST_HEIGHT);
            success = comparer.verifySame(mSoftwareArray, mHardwareArray, 0, TEST_WIDTH, TEST_WIDTH,
                    TEST_HEIGHT);
        }

        if (!success) {
            BitmapDumper.dumpBitmaps(bitmap1, bitmap2, getName(), this.getClass().getSimpleName(),
                    mDifferenceVisualizer);
        }

        assertTrue(debugMessage, success);
    }

    /**
     * Tests to see if a bitmap passes a verifier's test. If it doesn't the bitmap is saved to the
     * sdcard.
     */
    protected void assertBitmapIsVerified(Bitmap bitmap, BitmapVerifier bitmapVerifier,
            String debugMessage) {
        bitmap.getPixels(mSoftwareArray, 0, TEST_WIDTH, 0, 0,
                TEST_WIDTH, TEST_HEIGHT);
        boolean success = bitmapVerifier.verify(mSoftwareArray, 0, TEST_WIDTH, TEST_WIDTH, TEST_HEIGHT);
        if (!success) {
            Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, 0, 0, TEST_WIDTH, TEST_HEIGHT);
            BitmapDumper.dumpBitmap(croppedBitmap, getName(), this.getClass().getSimpleName());
            BitmapDumper.dumpBitmap(bitmapVerifier.getDifferenceBitmap(), getName() + "_verifier",
                    this.getClass().getSimpleName());
        }
        assertTrue(debugMessage, success);
    }

    protected TestCaseBuilder createTest() {
        mTestCaseBuilder = new TestCaseBuilder();
        return mTestCaseBuilder;
    }

    /**
     * Defines a group of CanvasClients, XML layouts, and WebView html files for testing.
     */
    protected class TestCaseBuilder {
        private List<TestCase> mTestCases;

        private TestCaseBuilder() {
            mTestCases = new ArrayList<TestCase>();
        }

        /**
         * Runs a test where the first test case is considered the "ideal" image and from there,
         * every test case is tested against it.
         */
        public void runWithComparer(BitmapComparer bitmapComparer) {
            if (mTestCases.size() == 0) {
                throw new IllegalStateException("Need at least one test to run");
            }

            Bitmap idealBitmap = captureRenderSpec(mTestCases.remove(0));

            for (TestCase testCase : mTestCases) {
                Bitmap testCaseBitmap = captureRenderSpec(testCase);
                assertBitmapsAreSimilar(idealBitmap, testCaseBitmap, bitmapComparer,
                        testCase.getDebugString());
            }
        }

        /**
         * Runs a test where each testcase is independent of the others and each is checked against
         * the verifier given.
         */
        public void runWithVerifier(BitmapVerifier bitmapVerifier) {
            if (mTestCases.size() == 0) {
                throw new IllegalStateException("Need at least one test to run");
            }

            for (TestCase testCase : mTestCases) {
                Bitmap testCaseBitmap = captureRenderSpec(testCase);
                assertBitmapIsVerified(testCaseBitmap, bitmapVerifier, testCase.getDebugString());
            }
        }

        /**
         * Runs a test where each testcase is run without verification. Should only be used
         * where custom CanvasClients, Views, or ViewInitializers do their own internal
         * test assertions.
         */
        public void runWithoutVerification() {
            runWithVerifier(new BitmapVerifier() {
                @Override
                public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
                    return true;
                }
            });
        }

        public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer) {
            return addLayout(layoutId, viewInitializer, false)
                    .addLayout(layoutId, viewInitializer, true);
        }

        public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer,
                                         boolean useHardware) {
            mTestCases.add(new TestCase(layoutId, viewInitializer, useHardware));
            return this;
        }

        public TestCaseBuilder addCanvasClient(CanvasClient canvasClient) {
            return addCanvasClient(null, canvasClient);
        }

        public TestCaseBuilder addCanvasClient(CanvasClient canvasClient, boolean useHardware) {
            return addCanvasClient(null, canvasClient, useHardware);
        }

        public TestCaseBuilder addCanvasClient(String debugString, CanvasClient canvasClient) {
            return addCanvasClient(debugString, canvasClient, false)
                    .addCanvasClient(debugString, canvasClient, true);
        }

        public TestCaseBuilder addCanvasClient(String debugString,
                    CanvasClient canvasClient, boolean useHardware) {
            mTestCases.add(new TestCase(canvasClient, debugString, useHardware));
            return this;
        }

        private List<TestCase> getTestCases() {
            return mTestCases;
        }
    }

    private class TestCase {
        public int layoutID;
        public ViewInitializer viewInitializer;

        public CanvasClient canvasClient;
        public String canvasClientDebugString;

        public boolean useHardware;
        public boolean wasTestRan = false;

        public TestCase(int layoutId, ViewInitializer viewInitializer, boolean useHardware) {
            this.layoutID = layoutId;
            this.viewInitializer = viewInitializer;
            this.useHardware = useHardware;
        }

        public TestCase(CanvasClient client, String debugString, boolean useHardware) {
            this.canvasClient = client;
            this.canvasClientDebugString = debugString;
            this.useHardware = useHardware;
        }

        public String getDebugString() {
            String debug = "";
            if (canvasClient != null) {
                debug += "CanvasClient : ";
                if (canvasClientDebugString != null) {
                    debug += canvasClientDebugString;
                } else {
                    debug += "no debug string given";
                }
            } else {
                debug += "Layout resource : " +
                        getActivity().getResources().getResourceName(layoutID);
            }
            debug += "\nTest ran in " + (useHardware ? "hardware" : "software") + "\n";
            return debug;
        }
    }
}
