/*
 * Copyright (C) 2013 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.text.cts;

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

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Picture;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.cts.WebViewOnUiThread;
import android.widget.EditText;
import android.widget.TextView;

import com.android.compatibility.common.util.NullWebViewUtils;

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

@MediumTest
@RunWith(AndroidJUnit4.class)
public class EmojiTest {
    private Context mContext;
    private EditText mEditText;

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

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

    /**
     * Tests all Emoji are defined in Character class
     */
    @Test
    public void testEmojiCodePoints() {
        for (int i = 0; i < EmojiConstants.ALL_EMOJI.length; i++) {
            assertTrue(Character.isDefined(EmojiConstants.ALL_EMOJI[i]));
        }
    }

    private String describeBitmap(final Bitmap bmp) {
        StringBuilder sb = new StringBuilder();
        sb.append("[ID:0x" + Integer.toHexString(System.identityHashCode(bmp)));
        sb.append(" " + Integer.toString(bmp.getWidth()) + "x" + Integer.toString(bmp.getHeight()));
        sb.append(" Config:");
        if (bmp.getConfig() == Bitmap.Config.ALPHA_8) {
            sb.append("ALPHA_8");
        } else if (bmp.getConfig() == Bitmap.Config.RGB_565) {
            sb.append("RGB_565");
        } else if (bmp.getConfig() == Bitmap.Config.ARGB_4444) {
            sb.append("ARGB_4444");
        } else if (bmp.getConfig() == Bitmap.Config.ARGB_8888) {
            sb.append("ARGB_8888");
        } else {
            sb.append("UNKNOWN");
        }
        sb.append("]");
        return sb.toString();
    }

    /**
     * Tests Emoji has different glyph for different meaning characters.
     * Test on Canvas, TextView, EditText and WebView
     */
    @UiThreadTest
    @Test
    public void testEmojiGlyph() {
        CaptureCanvas ccanvas = new CaptureCanvas(mContext);

        Bitmap mBitmapA, mBitmapB;  // Emoji displayed Bitmaps to compare

        int comparedCodePoints[][] = {   // Emojis should have different characters
            {0x1F436, 0x1F435},      // Dog(U+1F436) and Monkey(U+1F435)
            {0x26BD, 0x26BE},        // Soccer ball(U+26BD) and Baseball(U+26BE)
            {0x1F47B, 0x1F381},      // Ghost(U+1F47B) and wrapped present(U+1F381)
            {0x2764, 0x1F494},       // Heavy black heart(U+2764) and broken heart(U+1F494)
            {0x1F603, 0x1F33B}       // Smiling face with open mouth(U+1F603) and sunflower(U+1F33B)
        };

        for (int i = 0; i < comparedCodePoints.length; i++) {
            String baseMessage = "Glyph for U+" + Integer.toHexString(comparedCodePoints[i][0]) +
                " should be different from glyph for U+" +
                Integer.toHexString(comparedCodePoints[i][1]) + ". ";

            mBitmapA = ccanvas.capture(Character.toChars(comparedCodePoints[i][0]));
            mBitmapB = ccanvas.capture(Character.toChars(comparedCodePoints[i][1]));

            String bmpDiffMessage = describeBitmap(mBitmapA) + "vs" + describeBitmap(mBitmapB);
            assertFalse(baseMessage + bmpDiffMessage, mBitmapA.sameAs(mBitmapB));

            // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
            CaptureTextView cviewA = new CaptureTextView(mContext);
            mBitmapA = cviewA.capture(Character.toChars(comparedCodePoints[i][0]));
            CaptureTextView cviewB = new CaptureTextView(mContext);
            mBitmapB = cviewB.capture(Character.toChars(comparedCodePoints[i][1]));

            bmpDiffMessage = describeBitmap(mBitmapA) + "vs" + describeBitmap(mBitmapB);
            assertFalse(baseMessage + bmpDiffMessage, mBitmapA.sameAs(mBitmapB));

            CaptureEditText cedittextA = new CaptureEditText(mContext);
            mBitmapA = cedittextA.capture(Character.toChars(comparedCodePoints[i][0]));
            CaptureEditText cedittextB = new CaptureEditText(mContext);
            mBitmapB = cedittextB.capture(Character.toChars(comparedCodePoints[i][1]));

            bmpDiffMessage = describeBitmap(mBitmapA) + "vs" + describeBitmap(mBitmapB);
            assertFalse(baseMessage + bmpDiffMessage, mBitmapA.sameAs(mBitmapB));

            // Trigger activity bringup so we can determine if a WebView is available on this
            // device.
            if (NullWebViewUtils.isWebViewAvailable()) {
                CaptureWebView cwebview = new CaptureWebView();
                mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
                mBitmapB = cwebview.capture(Character.toChars(comparedCodePoints[i][1]));
                bmpDiffMessage = describeBitmap(mBitmapA) + "vs" + describeBitmap(mBitmapB);
                assertFalse(baseMessage + bmpDiffMessage, mBitmapA.sameAs(mBitmapB));
            }
        }
    }

    /**
     * Tests EditText handles Emoji
     */
    @LargeTest
    @Test
    public void testEmojiEditable() throws Throwable {
        int testedCodePoints[] = {
            0xAE,    // registered mark
            0x2764,    // heavy black heart
            0x1F353    // strawberry - surrogate pair sample. Count as two characters.
        };

        String origStr, newStr;

        // delete Emoji by sending KEYCODE_DEL
        for (int i = 0; i < testedCodePoints.length; i++) {
            origStr = "Test character  ";
            // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
            mActivityRule.runOnUiThread(() -> mEditText = new EditText(mContext));
            mEditText.setText(origStr + String.valueOf(Character.toChars(testedCodePoints[i])));

            // confirm the emoji is added.
            newStr = mEditText.getText().toString();
            assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);

            // Delete added character by sending KEYCODE_DEL event
            mActivityRule.runOnUiThread(() -> mEditText.dispatchKeyEvent(
                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)));
            InstrumentationRegistry.getInstrumentation().waitForIdleSync();

            newStr = mEditText.getText().toString();
            assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
        }
    }

    private static class CaptureCanvas extends View {

        String mTestStr;
        Paint paint = new Paint();

        CaptureCanvas(Context context) {
            super(context);
        }

        public void onDraw(Canvas canvas) {
            if (mTestStr != null) {
                canvas.drawText(mTestStr, 50, 50, paint);
            }
            return;
        }

        Bitmap capture(char c[]) {
            mTestStr = String.valueOf(c);
            invalidate();

            setDrawingCacheEnabled(true);
            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            layout(0, 0, 200,200);

            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
            setDrawingCacheEnabled(false);
            return bitmap;
        }

    }

    private static class CaptureTextView extends TextView {

        CaptureTextView(Context context) {
            super(context);
            setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
        }

        Bitmap capture(char c[]) {
            setText(String.valueOf(c));

            invalidate();

            setDrawingCacheEnabled(true);
            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            layout(0, 0, 200,200);

            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
            setDrawingCacheEnabled(false);
            return bitmap;
        }

    }

    private static class CaptureEditText extends EditText {

        CaptureEditText(Context context) {
            super(context);
            setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
        }

        Bitmap capture(char c[]) {
            setText(String.valueOf(c));

            invalidate();

            setDrawingCacheEnabled(true);
            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            layout(0, 0, 200,200);

            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
            setDrawingCacheEnabled(false);
            return bitmap;
        }

    }


    private class CaptureWebView {

        WebViewOnUiThread webViewOnUiThread;
        Bitmap bitmap;
        CaptureWebView() {
            webViewOnUiThread = new WebViewOnUiThread(mActivityRule,
                    mActivityRule.getActivity().getWebView());
        }

        Bitmap capture(char c[]) {

            webViewOnUiThread.loadDataAndWaitForCompletion(
                    "<html><body>" + String.valueOf(c) + "</body></html>",
                    "text/html; charset=utf-8", "utf-8");
            // The Chromium-powered WebView renders asynchronously and there's nothing reliable
            // we can easily wait for to be sure that capturePicture will return a fresh frame.
            // So, just sleep for a sufficient time.
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                return null;
            }

            Picture picture = webViewOnUiThread.capturePicture();
            if (picture == null || picture.getHeight() <= 0 || picture.getWidth() <= 0) {
                return null;
            } else {
                bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
                        Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
                picture.draw(canvas);
            }

            return bitmap;
        }

    }

}

