/*
 * Copyright (C) 2016 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.testclasses;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.ExactComparer;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.util.DisplayMetrics;

import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

@MediumTest
@RunWith(AndroidJUnit4.class)
public class HardwareBitmapTests extends ActivityTestBase {

    private Resources mRes;

    private static final BitmapFactory.Options HARDWARE_OPTIONS = createHardwareOptions();

    private static BitmapFactory.Options createHardwareOptions() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.HARDWARE;
        return options;
    }

    @Before
    public void setup() {
        mRes = getActivity().getResources();
    }

    @Test
    public void testDecodeResource() {
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                    HARDWARE_OPTIONS);
            canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_robot, new MSSIMComparer(0.95)));
    }

    @Test
    public void testCreateFromPicture() {
        final Rect rect = new Rect(10, 10, 80, 80);
        Picture picture = new Picture();
        {
            Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
            Paint p = new Paint();
            p.setAntiAlias(false);
            p.setColor(Color.BLUE);
            canvas.drawRect(rect, p);
            picture.endRecording();
        }
        Bitmap hardwareBitmap = Bitmap.createBitmap(picture);
        assertEquals(TEST_WIDTH, hardwareBitmap.getWidth());
        assertEquals(TEST_HEIGHT, hardwareBitmap.getHeight());
        assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
        createTest().addCanvasClient((canvas, width, height) -> {
            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
        }, true).runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, rect));
    }

    @Test
    public void testReadbackThroughPicture() {
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
        Picture picture = new Picture();
        {
            Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
            canvas.drawColor(Color.WHITE);
            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
            picture.endRecording();
        }
        assertTrue(picture.requiresHardwareAcceleration());
        Bitmap result = Bitmap.createBitmap(picture, picture.getWidth(), picture.getHeight(),
                Bitmap.Config.ARGB_8888);
        assertTrue(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_robot, new MSSIMComparer(0.95)).verify(result));
    }

    @Test
    public void testReadbackThroughPictureNoEndRecording() {
        // Exact same test as #testReadbackThroughPicture but with an omitted endRecording
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
        Picture picture = new Picture();
        {
            Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
            canvas.drawColor(Color.WHITE);
            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
        }
        // It will be true, but as endRecording hasn't been called yet it's still in the
        // "false" state from beginRecording()
        assertFalse(picture.requiresHardwareAcceleration());
        Bitmap result = Bitmap.createBitmap(picture, picture.getWidth(), picture.getHeight(),
                Bitmap.Config.ARGB_8888);
        assertTrue(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_robot, new MSSIMComparer(0.95)).verify(result));
    }

    @Test
    public void testCreateScaledBitmapFromPicture() {
        Picture picture = new Picture();
        {
            Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot, HARDWARE_OPTIONS);
            Canvas canvas = picture.beginRecording(bitmap.getWidth(), bitmap.getHeight());
            Paint paint = new Paint();
            paint.setFilterBitmap(true);
            paint.setAntiAlias(true);
            canvas.drawBitmap(bitmap, 0, 0, paint);
            picture.endRecording();
        }
        assertTrue(picture.requiresHardwareAcceleration());
        Bitmap scaled = Bitmap.createBitmap(picture, 24, 24, Bitmap.Config.HARDWARE);
        createTest().addCanvasClient((canvas, width, height) -> {
            assertEquals(Bitmap.Config.HARDWARE, scaled.getConfig());
            canvas.drawBitmap(scaled, 0, 0, null);
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_hardwaretest_create_scaled, new MSSIMComparer(0.9)));
    }

    @Test
    public void testBitmapRegionDecode() throws IOException {
        InputStream inputStream = mRes.openRawResource(R.drawable.robot);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputStream, false);
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = decoder.decodeRegion(new Rect(10, 15, 34, 39),
                    HARDWARE_OPTIONS);
            canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_headless_robot, new MSSIMComparer(0.95)));
    }

    @Test
    public void testBitmapConfigFromRGB565() {
        testBitmapCopy(R.drawable.robot, Bitmap.Config.RGB_565, Bitmap.Config.HARDWARE);
    }

    @Test
    public void testBitmapConfigFromARGB8888() {
        testBitmapCopy(R.drawable.robot, Bitmap.Config.ARGB_8888, Bitmap.Config.HARDWARE);
    }

    @Test
    public void testBitmapConfigFromA8() {
        Bitmap b = Bitmap.createBitmap(32, 32, Bitmap.Config.ALPHA_8);
        // we do not support conversion from A8
        assertNull(b.copy(Bitmap.Config.HARDWARE, false));
    }

    @Test
    public void testBitmapConfigFromHardwareToHardware() {
        testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.HARDWARE);
    }

    @Test
    public void testBitmapConfigFromHardwareToARGB8888() {
        testBitmapCopy(R.drawable.robot, Bitmap.Config.HARDWARE, Bitmap.Config.ARGB_8888);
    }

    @Test
    public void testSetDensity() {
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap bitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot);
            bitmap.setDensity(DisplayMetrics.DENSITY_LOW);
            canvas.drawBitmap(bitmap, 0, 0, null);
        }, true).addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                    HARDWARE_OPTIONS);
            hardwareBitmap.setDensity(DisplayMetrics.DENSITY_LOW);
            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
        }, true).runWithComparer(new ExactComparer());
    }

    @Test
    public void testNinePatch() {
        createTest().addCanvasClient((canvas, width, height) -> {
            InputStream is = mRes.openRawResource(R.drawable.blue_padded_square);
            NinePatchDrawable ninePatch = (NinePatchDrawable) Drawable.createFromResourceStream(
                    mRes, null, is, null, HARDWARE_OPTIONS);
            ninePatch.setBounds(0, 0, width, height);
            ninePatch.draw(canvas);
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_hardwaretest_ninepatch, new MSSIMComparer(0.95)));
    }

    @Test
    public void testCreateIdentityBitmap() {
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        Bitmap newBitmap = Bitmap.createBitmap(hardwareBitmap);
        assertEquals(hardwareBitmap, newBitmap);
    }

    @Test
    public void testCreateScaledBitmap() {
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                    HARDWARE_OPTIONS);
            Bitmap scaled = Bitmap.createScaledBitmap(hardwareBitmap, 24, 24, false);
            assertEquals(Bitmap.Config.HARDWARE, scaled.getConfig());
            canvas.drawBitmap(scaled, 0, 0, null);
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_hardwaretest_create_scaled, new MSSIMComparer(0.9)));
    }

    @Test
    public void testCreateSubsetBitmap() {
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                    HARDWARE_OPTIONS);
            Matrix matrix = new Matrix();
            matrix.setRotate(90);
            Bitmap cropped = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30);
            assertEquals(Bitmap.Config.HARDWARE, cropped.getConfig());
            canvas.drawBitmap(cropped, 0, 0, null);
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_hardwaretest_create_subset, new MSSIMComparer(0.9)));
    }

    @Test
    public void testCreateTransformedBitmap() {
        createTest().addCanvasClient((canvas, width, height) -> {
            Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                    HARDWARE_OPTIONS);
            Matrix matrix = new Matrix();
            matrix.setRotate(90);
            Bitmap transformed = Bitmap.createBitmap(hardwareBitmap, 7, 7, 30, 30, matrix, false);
            assertEquals(Bitmap.Config.HARDWARE, transformed.getConfig());
            canvas.drawBitmap(transformed, 0, 0, null);
        }, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
                R.drawable.golden_hardwaretest_create_transformed, new MSSIMComparer(0.9)));
    }

    @Test
    public void testCompressHardware() {
        Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
                HARDWARE_OPTIONS);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        assertTrue(hardwareBitmap.compress(Bitmap.CompressFormat.PNG, 50, stream));
        Bitmap decoded = BitmapFactory.decodeStream(
                new ByteArrayInputStream(stream.toByteArray()));
        createTest().addCanvasClient((canvas, width, height) -> {
            canvas.drawColor(Color.CYAN);
            canvas.drawBitmap(hardwareBitmap, 0, 0, null);
        }, true).addCanvasClient((canvas, width, height) -> {
            canvas.drawColor(Color.CYAN);
            canvas.drawBitmap(decoded, 0, 0, null);
        }, true).runWithComparer(new MSSIMComparer(0.99));

    }

    @Test
    public void testHardwareExtractAlpha() {
        Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
        bitmap.eraseColor(Color.argb(127, 250, 0, 0));
        bitmap.setPixel(25, 25, Color.BLUE);

        Bitmap hwBitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
        Bitmap alphaBitmap = hwBitmap.extractAlpha();
        assertEquals(Bitmap.Config.ALPHA_8, alphaBitmap.getConfig());
        assertTrue(Color.alpha(alphaBitmap.getPixel(25, 25)) >= 254);
        assertEquals(127, Color.alpha(alphaBitmap.getPixel(40, 40)));
    }

    private void testBitmapCopy(int id, Bitmap.Config from, Bitmap.Config to) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        options.inPreferredConfig = from;
        Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), id, options);
        assertEquals(from, bitmap.getConfig());

        createTest().addCanvasClient((canvas, width, height) -> {
            canvas.drawColor(Color.CYAN);
            canvas.drawBitmap(bitmap, 0, 0, null);
        }, true).addCanvasClient((canvas, width, height) -> {
            canvas.drawColor(Color.CYAN);
            Bitmap copy = bitmap.copy(to, false);
            assertNotNull(copy);
            assertEquals(to, copy.getConfig());
            canvas.drawBitmap(copy, 0, 0, null);
        }, true).runWithComparer(new MSSIMComparer(0.99));
    }
}
