/*
 * Copyright (C) 2010 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.gallery3d.ui;

import android.graphics.Rect;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.MotionEvent;

import junit.framework.TestCase;

@SmallTest
public class GLViewTest extends TestCase {
    @SuppressWarnings("unused")
    private static final String TAG = "GLViewTest";

    @SmallTest
    public void testVisibility() {
        GLViewMock a = new GLViewMock();
        assertEquals(GLView.VISIBLE, a.getVisibility());
        assertEquals(0, a.mOnVisibilityChangedCalled);
        a.setVisibility(GLView.INVISIBLE);
        assertEquals(GLView.INVISIBLE, a.getVisibility());
        assertEquals(1, a.mOnVisibilityChangedCalled);
        a.setVisibility(GLView.VISIBLE);
        assertEquals(GLView.VISIBLE, a.getVisibility());
        assertEquals(2, a.mOnVisibilityChangedCalled);
    }

    @SmallTest
    public void testComponents() {
        GLView view = new GLView();
        assertEquals(0, view.getComponentCount());
        try {
            view.getComponent(0);
            fail();
        } catch (IndexOutOfBoundsException ex) {
            // expected
        }

        GLView x = new GLView();
        GLView y = new GLView();
        view.addComponent(x);
        view.addComponent(y);
        assertEquals(2, view.getComponentCount());
        assertSame(x, view.getComponent(0));
        assertSame(y, view.getComponent(1));
        view.removeComponent(x);
        assertSame(y, view.getComponent(0));
        try {
            view.getComponent(1);
            fail();
        } catch (IndexOutOfBoundsException ex) {
            // expected
        }
        try {
            view.addComponent(y);
            fail();
        } catch (IllegalStateException ex) {
            // expected
        }
        view.addComponent(x);
        view.removeAllComponents();
        assertEquals(0, view.getComponentCount());
    }

    @SmallTest
    public void testBounds() {
        GLView view = new GLView();

        assertEquals(0, view.getWidth());
        assertEquals(0, view.getHeight());

        Rect b = view.bounds();
        assertEquals(0, b.left);
        assertEquals(0, b.top);
        assertEquals(0, b.right);
        assertEquals(0, b.bottom);

        view.layout(10, 20, 30, 100);
        assertEquals(20, view.getWidth());
        assertEquals(80, view.getHeight());

        b = view.bounds();
        assertEquals(10, b.left);
        assertEquals(20, b.top);
        assertEquals(30, b.right);
        assertEquals(100, b.bottom);
    }

    @SmallTest
    public void testParent() {
        GLView a = new GLView();
        GLView b = new GLView();
        assertNull(b.mParent);
        a.addComponent(b);
        assertSame(a, b.mParent);
        a.removeComponent(b);
        assertNull(b.mParent);
    }

    @SmallTest
    public void testRoot() {
        GLViewMock a = new GLViewMock();
        GLViewMock b = new GLViewMock();
        GLRoot r = new GLRootStub();
        GLRoot r2 = new GLRootStub();
        a.addComponent(b);

        // Attach to root r
        assertEquals(0, a.mOnAttachCalled);
        assertEquals(0, b.mOnAttachCalled);
        a.attachToRoot(r);
        assertEquals(1, a.mOnAttachCalled);
        assertEquals(1, b.mOnAttachCalled);
        assertSame(r, a.getGLRoot());
        assertSame(r, b.getGLRoot());

        // Detach from r
        assertEquals(0, a.mOnDetachCalled);
        assertEquals(0, b.mOnDetachCalled);
        a.detachFromRoot();
        assertEquals(1, a.mOnDetachCalled);
        assertEquals(1, b.mOnDetachCalled);

        // Attach to another root r2
        assertEquals(1, a.mOnAttachCalled);
        assertEquals(1, b.mOnAttachCalled);
        a.attachToRoot(r2);
        assertEquals(2, a.mOnAttachCalled);
        assertEquals(2, b.mOnAttachCalled);
        assertSame(r2, a.getGLRoot());
        assertSame(r2, b.getGLRoot());

        // Detach from r2
        assertEquals(1, a.mOnDetachCalled);
        assertEquals(1, b.mOnDetachCalled);
        a.detachFromRoot();
        assertEquals(2, a.mOnDetachCalled);
        assertEquals(2, b.mOnDetachCalled);
    }

    @SmallTest
    public void testRoot2() {
        GLView a = new GLViewMock();
        GLViewMock b = new GLViewMock();
        GLRoot r = new GLRootStub();

        a.attachToRoot(r);

        assertEquals(0, b.mOnAttachCalled);
        a.addComponent(b);
        assertEquals(1, b.mOnAttachCalled);

        assertEquals(0, b.mOnDetachCalled);
        a.removeComponent(b);
        assertEquals(1, b.mOnDetachCalled);
    }

    @SmallTest
    public void testInvalidate() {
        GLView a = new GLView();
        GLRootMock r = new GLRootMock();
        a.attachToRoot(r);
        assertEquals(0, r.mRequestRenderCalled);
        a.invalidate();
        assertEquals(1, r.mRequestRenderCalled);
    }

    @SmallTest
    public void testRequestLayout() {
        GLView a = new GLView();
        GLView b = new GLView();
        GLRootMock r = new GLRootMock();
        a.attachToRoot(r);
        a.addComponent(b);
        assertEquals(0, r.mRequestLayoutContentPaneCalled);
        b.requestLayout();
        assertEquals(1, r.mRequestLayoutContentPaneCalled);
    }

    @SmallTest
    public void testLayout() {
        GLViewMock a = new GLViewMock();
        GLViewMock b = new GLViewMock();
        GLViewMock c = new GLViewMock();
        GLRootMock r = new GLRootMock();

        a.attachToRoot(r);
        a.addComponent(b);
        a.addComponent(c);

        assertEquals(0, a.mOnLayoutCalled);
        a.layout(10, 20, 60, 100);
        assertEquals(1, a.mOnLayoutCalled);
        assertEquals(1, b.mOnLayoutCalled);
        assertEquals(1, c.mOnLayoutCalled);
        assertTrue(a.mOnLayoutChangeSize);
        assertTrue(b.mOnLayoutChangeSize);
        assertTrue(c.mOnLayoutChangeSize);

        // same size should not trigger onLayout
        a.layout(10, 20, 60, 100);
        assertEquals(1, a.mOnLayoutCalled);

        // unless someone requested it, but only those on the path
        // to the requester.
        assertEquals(0, r.mRequestLayoutContentPaneCalled);
        b.requestLayout();
        a.layout(10, 20, 60, 100);
        assertEquals(1, r.mRequestLayoutContentPaneCalled);
        assertEquals(2, a.mOnLayoutCalled);
        assertEquals(2, b.mOnLayoutCalled);
        assertEquals(1, c.mOnLayoutCalled);
    }

    @SmallTest
    public void testRender() {
        GLViewMock a = new GLViewMock();
        GLViewMock b = new GLViewMock();

        a.addComponent(b);
        GLCanvasStub canvas = new GLCanvasStub();
        assertEquals(0, a.mRenderBackgroundCalled);
        assertEquals(0, b.mRenderBackgroundCalled);
        a.render(canvas);
        assertEquals(1, a.mRenderBackgroundCalled);
        assertEquals(1, b.mRenderBackgroundCalled);
    }

    @SmallTest
    public void testMeasure() {
        GLViewMock a = new GLViewMock();
        GLViewMock b = new GLViewMock();
        GLViewMock c = new GLViewMock();
        GLRootMock r = new GLRootMock();

        a.addComponent(b);
        a.addComponent(c);
        a.attachToRoot(r);

        assertEquals(0, a.mOnMeasureCalled);
        a.measure(100, 200);
        assertEquals(1, a.mOnMeasureCalled);
        assertEquals(1, b.mOnMeasureCalled);
        assertEquals(100, a.mOnMeasureWidthSpec);
        assertEquals(200, a.mOnMeasureHeightSpec);
        assertEquals(100, b.mOnMeasureWidthSpec);
        assertEquals(200, b.mOnMeasureHeightSpec);
        assertEquals(100, a.getMeasuredWidth());
        assertEquals(200, b.getMeasuredHeight());

        // same spec should not trigger onMeasure
        a.measure(100, 200);
        assertEquals(1, a.mOnMeasureCalled);

        // unless someone requested it, but only those on the path
        // to the requester.
        b.requestLayout();
        a.measure(100, 200);
        assertEquals(2, a.mOnMeasureCalled);
        assertEquals(2, b.mOnMeasureCalled);
        assertEquals(1, c.mOnMeasureCalled);
    }

    class MyGLView extends GLView {
        private int mWidth;
        int mOnTouchCalled;
        int mOnTouchX;
        int mOnTouchY;
        int mOnTouchAction;

        public MyGLView(int width) {
            mWidth = width;
        }

        @Override
        protected void onLayout(boolean changeSize, int left, int top,
                int right, int bottom) {
            // layout children from left to right
            // call children's layout.
            int x = 0;
            for (int i = 0, n = getComponentCount(); i < n; ++i) {
                GLView item = getComponent(i);
                item.measure(0, 0);
                int w = item.getMeasuredWidth();
                int h = item.getMeasuredHeight();
                item.layout(x, 0, x + w, h);
                x += w;
            }
        }

        @Override
        protected void onMeasure(int widthSpec, int heightSpec) {
            setMeasuredSize(mWidth, 100);
        }

        @Override
        protected boolean onTouch(MotionEvent event) {
            mOnTouchCalled++;
            mOnTouchX = (int) event.getX();
            mOnTouchY = (int) event.getY();
            mOnTouchAction = event.getAction();
            return true;
        }
    }

    private MotionEvent NewMotionEvent(int action, int x, int y) {
        return MotionEvent.obtain(0, 0, action, x, y, 0);
    }

    @SmallTest
    public void testTouchEvent() {
        // We construct a tree with four nodes. Only the x coordinate is used:
        // A = [0..............................300)
        // B = [0......100)
        // C =             [100......200)
        // D =             [100..150)

        MyGLView a = new MyGLView(300);
        MyGLView b = new MyGLView(100);
        MyGLView c = new MyGLView(100);
        MyGLView d = new MyGLView(50);
        GLRoot r = new GLRootStub();

        a.addComponent(b);
        a.addComponent(c);
        c.addComponent(d);
        a.attachToRoot(r);
        a.layout(0, 0, 300, 100);

        int DOWN = MotionEvent.ACTION_DOWN;
        int UP = MotionEvent.ACTION_UP;
        int MOVE = MotionEvent.ACTION_MOVE;
        int CANCEL = MotionEvent.ACTION_CANCEL;

        // simple case
        assertEquals(0, a.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 250, 0));
        assertEquals(DOWN, a.mOnTouchAction);
        a.dispatchTouchEvent(NewMotionEvent(UP, 250, 0));
        assertEquals(UP, a.mOnTouchAction);
        assertEquals(2, a.mOnTouchCalled);

        // pass to a child, check the location is offseted.
        assertEquals(0, c.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0));
        a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0));
        assertEquals(75, c.mOnTouchX);
        assertEquals(0, c.mOnTouchY);
        assertEquals(2, c.mOnTouchCalled);
        assertEquals(2, a.mOnTouchCalled);

        // motion target cancel event
        assertEquals(0, d.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0));
        assertEquals(1, d.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(MOVE, 250, 0));
        assertEquals(2, d.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(MOVE, 50, 0));
        assertEquals(3, d.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 175, 0));
        assertEquals(4, d.mOnTouchCalled);
        assertEquals(CANCEL, d.mOnTouchAction);
        assertEquals(3, c.mOnTouchCalled);
        assertEquals(DOWN, c.mOnTouchAction);
        a.dispatchTouchEvent(NewMotionEvent(UP, 175, 0));

        // motion target is removed
        assertEquals(4, d.mOnTouchCalled);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 125, 0));
        assertEquals(5, d.mOnTouchCalled);
        a.removeComponent(c);
        assertEquals(6, d.mOnTouchCalled);
        assertEquals(CANCEL, d.mOnTouchAction);

        // invisible component should not get events
        assertEquals(2, a.mOnTouchCalled);
        assertEquals(0, b.mOnTouchCalled);
        b.setVisibility(GLView.INVISIBLE);
        a.dispatchTouchEvent(NewMotionEvent(DOWN, 50, 0));
        assertEquals(3, a.mOnTouchCalled);
        assertEquals(0, b.mOnTouchCalled);
    }
}
