package android.graphics.drawable.cts;

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

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.cts.R;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class AdaptiveIconDrawableTest {

    public static final String TAG = AdaptiveIconDrawableTest.class.getSimpleName();
    public static final boolean DEBUG = false;

    public static void L(String s, Object... parts) {
        Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts));
    }

    @Test
    public void testConstructor() {
        new AdaptiveIconDrawable(null, null);
        new AdaptiveIconDrawable(null, null, null);
    }

    @Test
    public void testInflate() throws Throwable {
        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);

        Resources r = InstrumentationRegistry.getTargetContext().getResources();
        XmlPullParser parser = r.getXml(R.layout.framelayout_layout);
        AttributeSet attrs = Xml.asAttributeSet(parser);

        // Should not throw inflate exception
        dr.inflate(r, parser, attrs);
    }

    @Test(expected=NullPointerException.class)
    public void testInflateNull() throws Throwable {
        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
        dr.inflate(null, null, null);
    }

    @Test
    public void testDraw() {
        Canvas c = new Canvas();
        AdaptiveIconDrawable dr = new AdaptiveIconDrawable(null, null);
        dr.draw(c);
    }

    @Test(expected=NullPointerException.class)
    public void testDrawNull() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        iconDrawable.setBounds(0, 0, 100, 100);
        iconDrawable.draw(null);
    }

    @Test
    public void testInvalidateDrawable() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        iconDrawable.invalidateDrawable(
            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass));
    }

    @Test
    public void testScheduleDrawable() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        iconDrawable.scheduleDrawable(
            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass),
            () -> {}, 10);

        // input null as params
        iconDrawable.scheduleDrawable(null, null, -1);
        // expected, no Exception thrown out, test success
    }

    @Test
    public void testUnscheduleDrawable() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        iconDrawable.unscheduleDrawable(
            InstrumentationRegistry.getTargetContext().getDrawable(R.drawable.pass), () -> {});

        // input null as params
        iconDrawable.unscheduleDrawable(null, null);
        // expected, no Exception thrown out, test success
    }

    @Test
    public void testGetChangingConfigurations() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        iconDrawable.setChangingConfigurations(11);
        assertEquals(11, iconDrawable.getChangingConfigurations());

        iconDrawable.setChangingConfigurations(-21);
        assertEquals(-21, iconDrawable.getChangingConfigurations());
    }

    @Test
    public void testGetAlpha() {
        ColorDrawable drawable = new ColorDrawable(Color.RED);
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(null, drawable);
        iconDrawable.setAlpha(128);
        assertEquals(128, iconDrawable.getAlpha());
    }

    @Test
    public void testGetMonochrome() {
        ColorDrawable drawable = new ColorDrawable(Color.RED);
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(null, null, drawable);
        assertEquals(drawable, iconDrawable.getMonochrome());
    }

    @Test
    public void testMonochromeInflated() {
        Resources r = InstrumentationRegistry.getTargetContext().getResources();
        AdaptiveIconDrawable iconDrawable = (AdaptiveIconDrawable) r.getDrawable(
                R.drawable.adaptiveicondrawable);
        assertNotNull(iconDrawable.getMonochrome());
    }

    /**
     * When setBound isn't called before draw method is called.
     * Nothing is drawn.
     */
    @Test
    public void testDrawWithoutSetBounds() throws Exception {
        Drawable backgroundDrawable = new ColorDrawable(Color.BLUE);
        Drawable foregroundDrawable = new ColorDrawable(Color.RED);
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(backgroundDrawable, foregroundDrawable);
        Context context = InstrumentationRegistry.getTargetContext();
        File dir = context.getExternalFilesDir(null);
        L("writing temp bitmaps to %s...", dir);

        final Bitmap bm_test = Bitmap.createBitmap(150, 150, Bitmap.Config.ARGB_8888);
        final Bitmap bm_org = bm_test.copy(Config.ARGB_8888, false);
        final Canvas can1 = new Canvas(bm_test);

        // Even when setBounds is not called, should not crash
        iconDrawable.draw(can1);
        // Draws nothing! Hence same as original.
        if (!equalBitmaps(bm_test, bm_org)) {
            findBitmapDifferences(bm_test, bm_org);
            fail("bm differs, check " + dir);
        }
    }

    /**
     * When setBound is called, translate accordingly.
     */
    @Test
    public void testDrawSetBounds() throws Exception {
        int dpi = 4 ;
        int top = 18 * dpi;
        int left = 18 * dpi;
        int right = 90 * dpi;
        int bottom = 90 * dpi;
        int width = right - left;
        int height = bottom - top;
        Context context = InstrumentationRegistry.getTargetContext();
        AdaptiveIconDrawable iconDrawable = (AdaptiveIconDrawable) context.getResources().getDrawable(android.R.drawable.sym_def_app_icon);
        File dir = context.getExternalFilesDir(null);
        L("writing temp bitmaps to %s...", dir);
        final Bitmap bm_org = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas can_org = new Canvas(bm_org);
        iconDrawable.setBounds(0, 0, width, height);
        iconDrawable.draw(can_org);

        // Tested bitmap is drawn from the adaptive icon drawable.
        final Bitmap bm_test = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas can_test = new Canvas(bm_test);

        iconDrawable.setBounds(left, top, right, bottom);
        can_test.translate(-left, -top);
        iconDrawable.draw(can_test);
        can_test.translate(left, top);

        if (DEBUG) {
            bm_org.compress(Bitmap.CompressFormat.PNG, 100,
                    new FileOutputStream(new File(dir, "adaptive-bm-original.png")));
            bm_test.compress(Bitmap.CompressFormat.PNG, 100,
                    new FileOutputStream(new File(dir, "adaptive-bm-test.png")));
        }
        Region region = new Region(new Rect(0, 0, width, height));

        Path circle = new Path();
        circle.addCircle(width / 2, height / 2,  (right - left)/2 -10 /* room for anti-alias */, Direction.CW);

        region.setPath(circle, region);
        if (!equalBitmaps(bm_test, bm_org, region)) {
            findBitmapDifferences(bm_test, bm_org);
            fail("bm differs, check " + dir);
        }
    }

    @Test
    public void testSetVisible() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        assertFalse(iconDrawable.setVisible(true, true)); /* unchanged */
        assertTrue(iconDrawable.setVisible(false, true)); /* changed */
        assertFalse(iconDrawable.setVisible(false, true)); /* unchanged */
    }

    @Test
    public void testSetAlpha() {
        Bitmap b = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
        Drawable bg = new BitmapDrawable(b);
        Drawable fg = new BitmapDrawable(b);
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(bg, fg);
        iconDrawable.setBounds(0, 0, 100, 100);

        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        iconDrawable.draw(canvas);
        assertEquals(255, Color.alpha(bitmap.getPixel(50, 50)));

        iconDrawable.setAlpha(200);
        bitmap.eraseColor(Color.TRANSPARENT);
        iconDrawable.draw(canvas);
        assertEquals(200, Color.alpha(bitmap.getPixel(50, 50)));
        assertEquals(200, bg.getAlpha());
        assertEquals(200, fg.getAlpha());

        iconDrawable.setAlpha(100);
        bitmap.eraseColor(Color.TRANSPARENT);
        iconDrawable.draw(canvas);
        assertEquals(100, Color.alpha(bitmap.getPixel(50, 50)));
        assertEquals(100, bg.getAlpha());
        assertEquals(100, fg.getAlpha());
    }

    @Test
    public void testSetColorFilter() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        ColorFilter cf = new ColorFilter();
        iconDrawable.setColorFilter(cf);

        // input null as param
        iconDrawable.setColorFilter(null);
        // expected, no Exception thrown out, test success
    }

    @Test
    public void testGetOpacity() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        // Drawable#getOpacity is deprecated, AdaptiveIconDrawable
        // should return PixelFormat.TRANSLUCENT always
        iconDrawable.setOpacity(PixelFormat.OPAQUE);
        assertEquals(PixelFormat.TRANSLUCENT, iconDrawable.getOpacity());

        iconDrawable.setOpacity(PixelFormat.TRANSPARENT);
        assertEquals(PixelFormat.TRANSLUCENT, iconDrawable.getOpacity());
    }

    @Test
    public void testIsStateful() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        assertFalse(iconDrawable.isStateful());

        iconDrawable = new AdaptiveIconDrawable(new StateListDrawable(), new ColorDrawable(Color.RED));
        assertTrue(iconDrawable.isStateful());
    }


    @Test
    public void testGetConstantState() {
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        ConstantState constantState = iconDrawable.getConstantState();
        assertNotNull(constantState);
    }

    @Test
    public void testMutate() {
        // Obtain the first instance, then mutate and modify a property held by
        // constant state. If mutate() works correctly, the property should not
        // be modified on the second or third instances.
        Resources res = InstrumentationRegistry.getTargetContext().getResources();
        AdaptiveIconDrawable first = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);
        AdaptiveIconDrawable pre = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);

        first.mutate().setBounds(0, 0, 100, 100);

        assertEquals("Modified first loaded instance", 100, first.getBounds().width());
        assertEquals("Did not modify pre-mutate() instance", 0, pre.getBounds().width());

        AdaptiveIconDrawable post = (AdaptiveIconDrawable) res.getDrawable(R.drawable.adaptive_icon_drawable, null);

        assertEquals("Did not modify post-mutate() instance", 0, post.getBounds().width());
    }

    @Test
    public void testGetForegroundBackground() {
        Context context = InstrumentationRegistry.getTargetContext();
        AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
            new ColorDrawable(Color.RED), new ColorDrawable(Color.BLUE));
        Drawable fgDrawable = iconDrawable.getForeground();
        Drawable bgDrawable = iconDrawable.getBackground();
        assertTrue("Foreground layer is color drawable.", fgDrawable instanceof ColorDrawable);
        assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof ColorDrawable);

        AdaptiveIconDrawable iconDrawableInflated =
            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
        fgDrawable = iconDrawableInflated.getForeground();
        bgDrawable = iconDrawableInflated.getBackground();
        assertTrue("Foreground layer is color drawable.", fgDrawable instanceof BitmapDrawable);
        assertTrue("Backgroud layer is color drawable.", bgDrawable instanceof BitmapDrawable);
    }

    @Test
    public void testGetIntrinsicWidth() {
        Context context = InstrumentationRegistry.getTargetContext();
        AdaptiveIconDrawable iconDrawableInflated =
            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
        int fgWidth = iconDrawableInflated.getForeground().getIntrinsicWidth();
        int bgWidth = iconDrawableInflated.getBackground().getIntrinsicWidth();
        float iconIntrinsicWidth = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
        assertEquals("Max intrinsic width of the layers should be icon's intrinsic width",
            (int) iconIntrinsicWidth, iconDrawableInflated.getIntrinsicWidth());
    }

    @Test
    public void testGetIntrinsicHeight() {
        Context context = InstrumentationRegistry.getTargetContext();
        AdaptiveIconDrawable iconDrawableInflated =
            (AdaptiveIconDrawable) context.getDrawable(R.drawable.adaptive_icon_drawable);
        int fgWidth = iconDrawableInflated.getForeground().getIntrinsicHeight();
        int bgWidth = iconDrawableInflated.getBackground().getIntrinsicHeight();
        float iconIntrinsicHeight = Math.max(fgWidth, bgWidth) / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
        assertEquals("Max intrinsic height of the layers should be icon's intrinsic height",
            (int) iconIntrinsicHeight, iconDrawableInflated.getIntrinsicHeight());
    }

    //
    // Utils
    //

    boolean equalBitmaps(Bitmap a, Bitmap b) {
      return equalBitmaps(a, b, null);
    }

    boolean equalBitmaps(Bitmap a, Bitmap b, Region region) {
        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) return false;

        final int w = a.getWidth();
        final int h = a.getHeight();
        int[] aPix = new int[w * h];
        int[] bPix = new int[w * h];

        if (region != null) {
            for (int i = 0; i < w; i++) {
                for (int j = 0; j < h; j++) {
                    int ra = (a.getPixel(i, j) >> 16) & 0xff;
                    int ga = (a.getPixel(i, j) >> 8) & 0xff;
                    int ba = a.getPixel(i, j) & 0xff;
                    int rb = (b.getPixel(i, j) >> 16) & 0xff;
                    int gb = (b.getPixel(i, j) >> 8) & 0xff;
                    int bb = b.getPixel(i, j) & 0xff;
                    if (region.contains(i, j) && a.getPixel(i, j) != b.getPixel(i, j) ) {
                        return false;
                    }
                }
            }
            return true;
        } else {
            a.getPixels(aPix, 0, w, 0, 0, w, h);
            b.getPixels(bPix, 0, w, 0, 0, w, h);
            return Arrays.equals(aPix, bPix);
        }
    }

    void findBitmapDifferences(Bitmap a, Bitmap b) {
        if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
            L("different sizes: %dx%d vs %dx%d",
                a.getWidth(), a.getHeight(), b.getWidth(), b.getHeight());
            return;
        }

        final int w = a.getWidth();
        final int h = a.getHeight();
        int[] aPix = new int[w * h];
        int[] bPix = new int[w * h];

        a.getPixels(aPix, 0, w, 0, 0, w, h);
        b.getPixels(bPix, 0, w, 0, 0, w, h);

        L("bitmap a (%dx%d)", w, h);
        printBits(aPix, w, h);
        L("bitmap b (%dx%d)", w, h);
        printBits(bPix, w, h);

        StringBuffer sb = new StringBuffer("Different pixels: ");
        for (int i=0; i<w; i++) {
            for (int j=0; j<h; j++) {
                if (aPix[i+w*j] != bPix[i+w*j]) {
                    sb.append(" ").append(i).append(",").append(j).append("<")
                        .append(aPix[i+w*j]).append(",").append(bPix[i+w*j]).append(">");
                }
            }
        }
        L(sb.toString());
    }

    static void printBits(int[] a, int w, int h) {
        final StringBuilder sb = new StringBuilder();
        for (int i=0; i<w; i++) {
            for (int j=0; j<h; j++) {
                sb.append(colorToChar(a[i+w*j]));
            }
            sb.append('\n');
        }
        L(sb.toString());
    }

    static char colorToChar(int color) {
        int sum = ((color >> 16) & 0xff)
            + ((color >> 8)  & 0xff)
            + ((color)       & 0xff);
        return GRADIENT[sum * (GRADIENT.length-1) / (3*0xff)];
    }
    static final char[] GRADIENT = " .:;+=xX$#".toCharArray();
}
