/*
 * 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 com.android.server.wm;

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

import android.graphics.Rect;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;

import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
 * Tests for the {@link TaskPositioner} class.
 *
 * runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TaskPositionerTests extends WindowTestsBase {

    private final boolean DEBUGGING = false;
    private final String TAG = "TaskPositionerTest";

    private final static int MOUSE_DELTA_X = 5;
    private final static int MOUSE_DELTA_Y = 5;

    private int mMinVisibleWidth;
    private int mMinVisibleHeight;
    private TaskPositioner mPositioner;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        final Display display = mDisplayContent.getDisplay();
        final DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        // This should be the same calculation as the TaskPositioner uses.
        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);

        mPositioner = new TaskPositioner(sWm);
        mPositioner.register(display);
    }

    /**
     * This tests that free resizing will allow to change the orientation as well
     * as does some basic tests (e.g. dragging in Y only will keep X stable).
     */
    @Test
    @Ignore
    public void testBasicFreeWindowResizing() throws Exception {
        final Rect r = new Rect(100, 220, 700, 520);
        final int midY = (r.top + r.bottom) / 2;

        // Start a drag resize starting upper left.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
        assertBoundsEquals(r, mPositioner.getWindowDragBounds());

        // Drag to a good landscape size.
        mPositioner.resizeDrag(0.0f, 0.0f);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a good portrait size.
        mPositioner.resizeDrag(400.0f, 0.0f);
        assertBoundsEquals(new Rect(400 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a too small size for the width.
        mPositioner.resizeDrag(2000.0f, r.top);
        assertBoundsEquals(
                new Rect(r.right - mMinVisibleWidth, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a too small size for the height.
        mPositioner.resizeDrag(r.left, 2000.0f);
        assertBoundsEquals(
                new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Start a drag resize left and see that only the left coord changes..
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);

        // Drag to the left.
        mPositioner.resizeDrag(0.0f, midY);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the right.
        mPositioner.resizeDrag(200.0f, midY);
        assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the top
        mPositioner.resizeDrag(r.left, 0.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the bottom
        mPositioner.resizeDrag(r.left, 1000.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
     */
    @Test
    @Ignore
    public void testFreeWindowResizingTestAllEdges() throws Exception {
        final Rect r = new Rect(100, 220, 700, 520);
        final int midX = (r.left + r.right) / 2;
        final int midY = (r.top + r.bottom) / 2;

        // Drag upper left.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(0.0f, 0.0f);
        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);

        // Drag upper.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(0.0f, 0.0f);
        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);

        // Drag upper right.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(r.right + 100, 0.0f);
        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
        assertTrue(r.top != mPositioner.getWindowDragBounds().top);
        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);

        // Drag right.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY, r);
        mPositioner.resizeDrag(r.right + 100, 0.0f);
        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);

        // Drag bottom right.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/,
                r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
        assertTrue(r.right != mPositioner.getWindowDragBounds().right);
        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);

        // Drag bottom.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
        assertEquals(r.left, mPositioner.getWindowDragBounds().left);
        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);

        // Drag bottom left.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
        mPositioner.resizeDrag(0.0f, r.bottom + 100);
        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
        assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);

        // Drag left.
        mPositioner.startDrag(true /*resizing*/,
                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX, r);
        mPositioner.resizeDrag(0.0f, r.bottom + 100);
        assertTrue(r.left != mPositioner.getWindowDragBounds().left);
        assertEquals(r.right, mPositioner.getWindowDragBounds().right);
        assertEquals(r.top, mPositioner.getWindowDragBounds().top);
        assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
    }

    /**
     * This tests that a constrained landscape window will keep the aspect and do the
     * right things upon resizing when dragged from the top left corner.
     */
    @Test
    @Ignore
    public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
        final Rect r = new Rect(100, 220, 700, 520);

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
        assertBoundsEquals(r, mPositioner.getWindowDragBounds());

        // Drag to a good landscape size.
        mPositioner.resizeDrag(0.0f, 0.0f);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a good portrait size.
        mPositioner.resizeDrag(400.0f, 0.0f);
        int width = Math.round((float) (r.bottom - MOUSE_DELTA_Y) * MIN_ASPECT);
        assertBoundsEquals(new Rect(r.right - width, MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a too small size for the width.
        mPositioner.resizeDrag(2000.0f, r.top);
        final int w = mMinVisibleWidth;
        final int h = Math.round(w / MIN_ASPECT);
        assertBoundsEquals(new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a too small size for the height.
        mPositioner.resizeDrag(r.left, 2000.0f);
        assertBoundsEquals(
                new Rect(r.left + MOUSE_DELTA_X, r.bottom - mMinVisibleHeight, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that a constrained landscape window will keep the aspect and do the
     * right things upon resizing when dragged from the left corner.
     */
    @Test
    @Ignore
    public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
        final Rect r = new Rect(100, 220, 700, 520);
        final int midY = (r.top + r.bottom) / 2;

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);

        // Drag to the left.
        mPositioner.resizeDrag(0.0f, midY);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the right.
        mPositioner.resizeDrag(200.0f, midY);
        assertBoundsEquals(new Rect(200 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag all the way to the right and see the height also shrinking.
        mPositioner.resizeDrag(2000.0f, midY);
        final int w = mMinVisibleWidth;
        final int h = Math.round((float)w / MIN_ASPECT);
        assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
                mPositioner.getWindowDragBounds());

        // Drag to the top.
        mPositioner.resizeDrag(r.left, 0.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the bottom.
        mPositioner.resizeDrag(r.left, 1000.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that a constrained landscape window will keep the aspect and do the
     * right things upon resizing when dragged from the top corner.
     */
    @Test
    @Ignore
    public void testLandscapePreservedWindowResizingDragTop() throws Exception {
        final Rect r = new Rect(100, 220, 700, 520);
        final int midX = (r.left + r.right) / 2;

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);

        // Drag to the left (no change).
        mPositioner.resizeDrag(0.0f, r.top);
        assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the right (no change).
        mPositioner.resizeDrag(2000.0f, r.top);
        assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the top.
        mPositioner.resizeDrag(300.0f, 0.0f);
        int h = r.bottom - MOUSE_DELTA_Y;
        int w = Math.max(r.right - r.left, Math.round(h * MIN_ASPECT));
        assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the bottom.
        mPositioner.resizeDrag(r.left, 1000.0f);
        h = mMinVisibleHeight;
        assertBoundsEquals(new Rect(r.left, r.bottom - h, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that a constrained portrait window will keep the aspect and do the
     * right things upon resizing when dragged from the top left corner.
     */
    @Test
    @Ignore
    public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
        final Rect r = new Rect(330, 100, 630, 600);

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
        assertBoundsEquals(r, mPositioner.getWindowDragBounds());

        // Drag to a good landscape size.
        mPositioner.resizeDrag(0.0f, 0.0f);
        int height = Math.round((float) (r.right - MOUSE_DELTA_X) * MIN_ASPECT);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.bottom - height, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a good portrait size.
        mPositioner.resizeDrag(500.0f, 0.0f);
        assertBoundsEquals(new Rect(500 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to a too small size for the height and the the width shrinking.
        mPositioner.resizeDrag(r.left + MOUSE_DELTA_X, 2000.0f);
        final int w = Math.max(mMinVisibleWidth, Math.round(mMinVisibleHeight / MIN_ASPECT));
        final int h = Math.max(mMinVisibleHeight, Math.round(w * MIN_ASPECT));
        assertBoundsEquals(
                new Rect(r.right - w, r.bottom - h, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that a constrained portrait window will keep the aspect and do the
     * right things upon resizing when dragged from the left corner.
     */
    @Test
    @Ignore
    public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
        final Rect r = new Rect(330, 100, 630, 600);
        final int midY = (r.top + r.bottom) / 2;

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);

        // Drag to the left.
        mPositioner.resizeDrag(0.0f, midY);
        int w = r.right - MOUSE_DELTA_X;
        int h = Math.round(w * MIN_ASPECT);
        assertBoundsEquals(new Rect(MOUSE_DELTA_X, r.top, r.right, r.top + h),
                mPositioner.getWindowDragBounds());

        // Drag to the right.
        mPositioner.resizeDrag(450.0f, midY);
        assertBoundsEquals(new Rect(450 + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag all the way to the right.
        mPositioner.resizeDrag(2000.0f, midY);
        w = mMinVisibleWidth;
        h = Math.max(Math.round((float)w * MIN_ASPECT), r.height());
        assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
                mPositioner.getWindowDragBounds());

        // Drag to the top.
        mPositioner.resizeDrag(r.left, 0.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the bottom.
        mPositioner.resizeDrag(r.left, 1000.0f);
        assertBoundsEquals(new Rect(r.left + MOUSE_DELTA_X, r.top, r.right, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    /**
     * This tests that a constrained portrait window will keep the aspect and do the
     * right things upon resizing when dragged from the top corner.
     */
    @Test
    @Ignore
    public void testPortraitPreservedWindowResizingDragTop() throws Exception {
        final Rect r = new Rect(330, 100, 630, 600);
        final int midX = (r.left + r.right) / 2;

        mPositioner.startDrag(true /*resizing*/,
                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);

        // Drag to the left (no change).
        mPositioner.resizeDrag(0.0f, r.top);
        assertBoundsEquals(new Rect(r.left, r.top + MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the right (no change).
        mPositioner.resizeDrag(2000.0f, r.top);
        assertBoundsEquals(new Rect(r.left , r.top + MOUSE_DELTA_Y, r.right, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the top.
        mPositioner.resizeDrag(300.0f, 0.0f);
        int h = r.bottom - MOUSE_DELTA_Y;
        int w = Math.min(r.width(), Math.round(h / MIN_ASPECT));
        assertBoundsEquals(new Rect(r.left, MOUSE_DELTA_Y, r.left + w, r.bottom),
                mPositioner.getWindowDragBounds());

        // Drag to the bottom.
        mPositioner.resizeDrag(r.left, 1000.0f);
        h = Math.max(mMinVisibleHeight, Math.round(mMinVisibleWidth * MIN_ASPECT));
        w = Math.round(h / MIN_ASPECT);
        assertBoundsEquals(new Rect(r.left, r.bottom - h, r.left + w, r.bottom),
                mPositioner.getWindowDragBounds());
    }

    private void assertBoundsEquals(Rect expected, Rect actual) {
        if (DEBUGGING) {
            if (!expected.equals(actual)) {
                Log.e(TAG, "rect(" + actual.toString() + ") != isRect(" + actual.toString()
                        + ") " + Log.getStackTraceString(new Throwable()));
            }
        }
        assertEquals(expected.left, actual.left);
        assertEquals(expected.right, actual.right);
        assertEquals(expected.top, actual.top);
        assertEquals(expected.bottom, actual.bottom);
    }
}
