/*
 * Copyright (C) 2015 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.graphics.drawable.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.app.Activity;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.cts.ImageViewCtsActivity;
import android.graphics.cts.R;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;

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

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

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@MediumTest
@RunWith(AndroidJUnit4.class)
public class IconTest {
    private static final long TIMEOUT_MS = 1000;

    private Activity mActivity;
    private Icon mIcon;

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

    @Before
    public void setup() {
        mActivity = mActivityRule.getActivity();
    }

    @Test
    public void testBitmapIcon() {
        verifyIconValidity(
                Icon.createWithBitmap(Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888)));
    }

    @Test
    public void testDataIcon() {
        byte[] data = new byte[4];
        data[0] = data[1] = data[2] = data[3] = (byte)255;
        verifyIconValidity(Icon.createWithData(data, 0, 4));
    }

    @Test
    public void testFileIcon() throws IOException {
        File file = new File(mActivity.getFilesDir(), "testimage.jpg");
        try {
            writeSampleImage(file);
            assertTrue(file.exists());

            verifyIconValidity(Icon.createWithFilePath(file.getPath()));

            verifyIconValidity(Icon.createWithContentUri(Uri.fromFile(file)));

            verifyIconValidity(Icon.createWithContentUri(file.toURI().toString()));
        } finally {
            file.delete();
        }
    }

    @Test
    public void testResourceIcon() {
        verifyIconValidity(Icon.createWithResource(mActivity, R.drawable.bmp_test));

        verifyIconValidity(Icon.createWithResource(
                mActivity.getPackageName(), R.drawable.bmp_test));
    }

    @Test
    public void testLoadDrawableAsync() throws Throwable {
        mIcon = Icon.createWithBitmap(Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888));

        Icon.OnDrawableLoadedListener mockListener = mock(Icon.OnDrawableLoadedListener.class);
        mActivityRule.runOnUiThread(
                () -> mIcon.loadDrawableAsync(mActivity, mockListener, new Handler()));
        // Verify that there was exactly one call to the passed listener's callback within the
        // predetermined timeout
        Thread.sleep(TIMEOUT_MS);
        verify(mockListener, times(1)).onDrawableLoaded(any());
    }

    @Test
    public void testLoadDrawableAsyncWithMessage() throws Throwable {
        mIcon = Icon.createWithBitmap(Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888));

        Runnable mockRunnable = mock(Runnable.class);
        mActivityRule.runOnUiThread(
                () -> mIcon.loadDrawableAsync(mActivity, Message.obtain(new Handler(),
                        mockRunnable)));
        // Verify that there was exactly one call to the passed Runnable's run within the
        // predetermined timeout
        Thread.sleep(TIMEOUT_MS);
        verify(mockRunnable, times(1)).run();
    }

    @Test
    public void testBitmapIcon_getType() {
        Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888));
        assertEquals(Icon.TYPE_BITMAP, icon.getType());
    }

    @Test
    public void testDataIcon_getType() {
        byte[] data = new byte[4];
        data[0] = data[1] = data[2] = data[3] = (byte) 255;
        Icon icon = Icon.createWithData(data, 0, 4);
        assertEquals(Icon.TYPE_DATA, icon.getType());
    }

    @Test
    public void testFileIcon_getType() throws IOException {
        File file = new File(mActivity.getFilesDir(), "testimage.jpg");
        try {
            writeSampleImage(file);
            assertTrue(file.exists());
            String filePath = file.toURI().getPath();

            Icon icon = Icon.createWithFilePath(file.getPath());
            assertEquals(Icon.TYPE_URI, icon.getType());
            assertEquals(filePath, icon.getUri().getPath());

            icon = Icon.createWithContentUri(Uri.fromFile(file));
            assertEquals(Icon.TYPE_URI, icon.getType());
            assertEquals(filePath, icon.getUri().getPath());

            icon = Icon.createWithContentUri(file.toURI().toString());
            assertEquals(Icon.TYPE_URI, icon.getType());
            assertEquals(filePath, icon.getUri().getPath());
        } finally {
            file.delete();
        }
    }

    @Test
    public void testResourceIcon_getType() {
        Icon icon = Icon.createWithResource("com.android.cts.testpkg", R.drawable.bmp_test);
        assertEquals(Icon.TYPE_RESOURCE, icon.getType());
        assertEquals("com.android.cts.testpkg", icon.getResPackage());
        assertEquals(R.drawable.bmp_test, icon.getResId());
    }

    private void writeSampleImage(File imagefile) throws IOException {
        try (InputStream source = mActivity.getResources().openRawResource(R.drawable.testimage);
             OutputStream target = new FileOutputStream(imagefile)) {
            byte[] buffer = new byte[1024];
            for (int len = source.read(buffer); len >= 0; len = source.read(buffer)) {
                target.write(buffer, 0, len);
            }
        }
    }

    // Check if the created icon is valid and doesn't cause crashes for the public methods.
    private void verifyIconValidity(Icon icon) {
        assertNotNull(icon);

        // tint properties.
        icon.setTint(Color.BLUE);
        icon.setTintList(ColorStateList.valueOf(Color.RED));
        icon.setTintMode(PorterDuff.Mode.XOR);

        // Parcelable methods.
        icon.describeContents();
        Parcel parcel = Parcel.obtain();
        icon.writeToParcel(parcel, 0);

        parcel.setDataPosition(0);
        assertNotNull(Icon.CREATOR.createFromParcel(parcel));

        // loading drawable synchronously.
        assertNotNull(icon.loadDrawable(mActivity));

        parcel.recycle();
    }
}
