/*
 * Copyright (C) 2023 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.server.wm.other;

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.graphics.PixelFormat;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.text.SpannedString;
import android.view.Gravity;
import android.view.WindowManager;

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

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

@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class WindowManager_LayoutParamsTest {
    private static final int WINDOW_WIDTH = 320;
    private static final int WINDOW_HEIGHT = 480;
    private static final int XPOS = 10;
    private static final int YPOS = 15;
    private static final String PACKAGE_NAME = "android.content";
    private static final String TITLE = "params title";
    private static final String PARAMS_TITLE = "params title";
    private static final float HORIZONTAL_MARGIN = 1.0f;
    private static final float VERTICAL_MARGIN = 3.0f;
    private static final float ALPHA = 1.0f;
    private static final float DIM_AMOUNT = 1.0f;
    private static final float HORIZONTAL_WEIGHT = 1.0f;
    private static final float MARGIN = 1.0f;
    private static final float VERTICAL_WEIGHT = 1.0f;
    private static final int WINDOW_ANIMATIONS = 6;

    private WindowManager.LayoutParams mLayoutParams;

    @Test
    public void testConstructor() {
        new WindowManager.LayoutParams();

        new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_APPLICATION);

        new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER);

        new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);

        new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);

        new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT, XPOS, YPOS,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);

        IBinder binder = new Binder();
        mLayoutParams = new WindowManager.LayoutParams();
        mLayoutParams.token = binder;
        mLayoutParams.packageName = PACKAGE_NAME;
        mLayoutParams.setTitle(TITLE);
        Parcel parcel = Parcel.obtain();
        mLayoutParams.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);

        new WindowManager.LayoutParams(parcel);
        assertTrue(WindowManager.LayoutParams.mayUseInputMethod(0));
        assertFalse(WindowManager.LayoutParams.mayUseInputMethod(
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM));
        assertFalse(WindowManager.LayoutParams
                .mayUseInputMethod(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE));
        assertFalse(WindowManager.LayoutParams
                .mayUseInputMethod(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM));
    }

    @Test
    public void testCopyFrom() {
        mLayoutParams = new WindowManager.LayoutParams();
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_BASE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER);
        assertEquals(WindowManager.LayoutParams.TYPE_CHANGED
                | WindowManager.LayoutParams.FLAGS_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(WindowManager.LayoutParams.TYPE_BASE_APPLICATION, mLayoutParams.type);
        assertEquals(WindowManager.LayoutParams.FLAG_DITHER, mLayoutParams.flags);

        mLayoutParams = new WindowManager.LayoutParams();
        params = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED
                | WindowManager.LayoutParams.FLAGS_CHANGED
                | WindowManager.LayoutParams.FORMAT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(WINDOW_WIDTH, mLayoutParams.width);
        assertEquals(WINDOW_HEIGHT, mLayoutParams.height);
        assertEquals(WindowManager.LayoutParams.FLAG_DITHER, mLayoutParams.flags);
        assertEquals(PixelFormat.JPEG, mLayoutParams.format);

        params = new WindowManager.LayoutParams();
        params.setTitle(PARAMS_TITLE);
        params.accessibilityTitle = PARAMS_TITLE;
        params.alpha = ALPHA - 0.5f;
        params.windowAnimations = WINDOW_ANIMATIONS;
        params.dimAmount = DIM_AMOUNT - 1.0f;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.TITLE_CHANGED
                | WindowManager.LayoutParams.ALPHA_CHANGED
                | WindowManager.LayoutParams.ANIMATION_CHANGED
                | WindowManager.LayoutParams.DIM_AMOUNT_CHANGED
                | WindowManager.LayoutParams.ACCESSIBILITY_TITLE_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.getTitle(), mLayoutParams.getTitle());
        assertEquals(params.alpha, mLayoutParams.alpha, 0.0f);
        assertEquals(params.dimAmount, mLayoutParams.dimAmount, 0.0f);

        params = new WindowManager.LayoutParams();
        params.gravity = Gravity.TOP;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.gravity, mLayoutParams.gravity);

        params = new WindowManager.LayoutParams();
        params.horizontalMargin = HORIZONTAL_MARGIN;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.horizontalMargin, mLayoutParams.horizontalMargin, 0.0f);

        params = new WindowManager.LayoutParams();
        params.horizontalWeight = HORIZONTAL_WEIGHT;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.horizontalWeight, mLayoutParams.horizontalWeight, 0.0f);

        params = new WindowManager.LayoutParams();
        params.verticalMargin = MARGIN;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.verticalMargin, mLayoutParams.verticalMargin, 0.0f);

        params = new WindowManager.LayoutParams();
        params.verticalWeight = VERTICAL_WEIGHT;
        mLayoutParams = new WindowManager.LayoutParams();
        assertEquals(WindowManager.LayoutParams.LAYOUT_CHANGED,
                mLayoutParams.copyFrom(params));
        assertEquals(params.verticalWeight, mLayoutParams.verticalWeight, 0.0f);

        params = new WindowManager.LayoutParams();
        params.setWindowContextToken(new Binder());
        mLayoutParams = new WindowManager.LayoutParams();
        // Assert no change returned from copyFrom().
        assertEquals(0, mLayoutParams.copyFrom(params));
        assertEquals(params.getWindowContextToken(), mLayoutParams.getWindowContextToken());
    }

    @Test
    public void testDescribeContents() {
        mLayoutParams = new WindowManager.LayoutParams();

        assertEquals(0, mLayoutParams.describeContents());
    }

    @Test
    public void testAccessTitle() {
        String title = "";
        mLayoutParams = new WindowManager.LayoutParams();

        mLayoutParams.setTitle(null);
        assertEquals(title, mLayoutParams.getTitle());

        title = "Android Test Title";
        mLayoutParams.setTitle(title);
        assertEquals(title, mLayoutParams.getTitle());

        SpannedString spannedTitle = new SpannedString(title);
        mLayoutParams.setTitle(spannedTitle);
        assertEquals(spannedTitle, mLayoutParams.getTitle());
    }

    @Test
    public void testToString() {
        mLayoutParams = new WindowManager.LayoutParams();
        assertNotNull(mLayoutParams.toString());

        mLayoutParams = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT, XPOS, YPOS,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);
        assertNotNull(mLayoutParams.toString());
    }

    @Test
    public void testWriteToParcel() {
        IBinder binder = new Binder();
        mLayoutParams = new WindowManager.LayoutParams(WINDOW_WIDTH, WINDOW_HEIGHT, XPOS, YPOS,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_DITHER, PixelFormat.JPEG);
        mLayoutParams.memoryType = WindowManager.LayoutParams.MEMORY_TYPE_HARDWARE;
        mLayoutParams.gravity = Gravity.TOP;
        mLayoutParams.horizontalMargin = HORIZONTAL_MARGIN;
        mLayoutParams.verticalMargin = VERTICAL_MARGIN;
        mLayoutParams.windowAnimations = WINDOW_ANIMATIONS;
        mLayoutParams.token = binder;
        mLayoutParams.packageName = PACKAGE_NAME;
        mLayoutParams.setTitle(PARAMS_TITLE);
        mLayoutParams.setWindowContextToken(binder);
        Parcel parcel = Parcel.obtain();

        mLayoutParams.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        WindowManager.LayoutParams out =
            WindowManager.LayoutParams.CREATOR.createFromParcel(parcel);
        assertEquals(0, out.copyFrom(mLayoutParams));
        assertEquals(binder, out.getWindowContextToken());

        try {
            mLayoutParams.writeToParcel(null, 0);
            fail("should throw NullPointerException");
        } catch (NullPointerException e) {
            // expected
        }
    }
}
