/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.ide.common.layout;

import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ID;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.api.DropFeedback;
import com.android.ide.common.api.IClientRulesEngine;
import com.android.ide.common.api.IDragElement;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.IValidator;
import com.android.ide.common.api.IViewMetadata;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

/**
 * Common layout helpers from LayoutRule tests
 */
@SuppressWarnings("javadoc")
public class LayoutTestBase extends TestCase {
    /**
     * Helper function used by tests to drag a button into a canvas containing
     * the given children.
     *
     * @param rule The rule to test on
     * @param targetNode The target layout node to drag into
     * @param dragBounds The (original) bounds of the dragged item
     * @param dropPoint The drag point we should drag to and drop
     * @param secondDropPoint An optional second drag point to drag to before
     *            drawing graphics and dropping (or null if not applicable)
     * @param insertIndex The expected insert position we end up with after
     *            dropping at the dropPoint
     * @param currentIndex If the dragged widget is already in the canvas this
     *            should be its child index; if not, pass in -1
     * @param graphicsFragments This is a varargs array of String fragments
     *            we expect to see in the graphics output on the drag over
     *            event.
     * @return The inserted node
     */
    protected INode dragInto(IViewRule rule, INode targetNode, Rect dragBounds, Point dropPoint,
            Point secondDropPoint, int insertIndex, int currentIndex,
            String... graphicsFragments) {

        String draggedButtonId = (currentIndex == -1) ? "@+id/DraggedButton" : targetNode
                .getChildren()[currentIndex].getStringAttr(ANDROID_URI, ATTR_ID);

        IDragElement[] elements = TestDragElement.create(TestDragElement.create(
                "android.widget.Button", dragBounds).id(draggedButtonId));

        // Enter target
        DropFeedback feedback = rule.onDropEnter(targetNode, null/*targetView*/, elements);
        assertNotNull(feedback);
        assertFalse(feedback.invalidTarget);
        assertNotNull(feedback.painter);

        if (currentIndex != -1) {
            feedback.sameCanvas = true;
        }

        // Move near top left corner of the target
        feedback = rule.onDropMove(targetNode, elements, feedback, dropPoint);
        assertNotNull(feedback);

        if (secondDropPoint != null) {
            feedback = rule.onDropMove(targetNode, elements, feedback, secondDropPoint);
            assertNotNull(feedback);
        }

        if (insertIndex == -1) {
            assertTrue(feedback.invalidTarget);
        } else {
            assertFalse(feedback.invalidTarget);
        }

        // Paint feedback and make sure it's what we expect
        TestGraphics graphics = new TestGraphics();
        assertNotNull(feedback.painter);
        feedback.painter.paint(graphics, targetNode, feedback);
        String drawn = graphics.getDrawn().toString();

        // Check that each graphics fragment is drawn
        for (String fragment : graphicsFragments) {
            if (!drawn.contains(fragment)) {
                // Get drawn-output since unit test truncates message in below
                // contains-assertion
                System.out.println("Could not find: " + fragment);
                System.out.println("Full graphics output: " + drawn);
            }
            assertTrue(fragment + " not found; full=" + drawn, drawn.contains(fragment));
        }

        // Attempt a drop?
        if (insertIndex == -1) {
            // No, not expected to succeed (for example, when drop point is over an
            // invalid region in RelativeLayout) - just return.
            return null;
        }
        int childrenCountBefore = targetNode.getChildren().length;
        rule.onDropped(targetNode, elements, feedback, dropPoint);

        if (currentIndex == -1) {
            // Inserting new from outside
            assertEquals(childrenCountBefore+1, targetNode.getChildren().length);
        } else {
            // Moving from existing; must remove in old position first
            ((TestNode) targetNode).removeChild(currentIndex);

            assertEquals(childrenCountBefore, targetNode.getChildren().length);
        }
        // Ensure that it's inserted in the right place
        String actualId = targetNode.getChildren()[insertIndex].getStringAttr(
                ANDROID_URI, ATTR_ID);
        if (!draggedButtonId.equals(actualId)) {
            // Using assertEquals instead of fail to get nice diff view on test
            // failure
            List<String> childrenIds = new ArrayList<String>();
            for (INode child : targetNode.getChildren()) {
                childrenIds.add(child.getStringAttr(ANDROID_URI, ATTR_ID));
            }
            int index = childrenIds.indexOf(draggedButtonId);
            String message = "Button found at index " + index + " instead of " + insertIndex
                    + " among " + childrenIds;
            System.out.println(message);
            assertEquals(message, draggedButtonId, actualId);
        }


        return targetNode.getChildren()[insertIndex];
    }

    /**
     * Utility method for asserting that two collections contain exactly the
     * same elements (regardless of order)
     * @param expected expected collection
     * @param actual  actual collection
     */
    public static void assertContainsSame(Collection<String> expected, Collection<String> actual) {
        if (expected.size() != actual.size()) {
            fail("Collection sizes differ; expected " + expected.size() + " but was "
                    + actual.size());
        }

        // Sort prior to comparison to ensure we have the same elements
        // regardless of order
        List<String> expectedList = new ArrayList<String>(expected);
        Collections.sort(expectedList);
        List<String> actualList = new ArrayList<String>(actual);
        Collections.sort(actualList);
        // Instead of just assertEquals(expectedList, actualList);
        // we iterate one element at a time so we can show the first
        // -difference-.
        for (int i = 0; i < expectedList.size(); i++) {
            String expectedElement = expectedList.get(i);
            String actualElement = actualList.get(i);
            if (!expectedElement.equals(actualElement)) {
                System.out.println("Expected items: " + expectedList);
                System.out.println("Actual items  : " + actualList);
            }
            assertEquals("Collections differ; first difference:", expectedElement, actualElement);
        }
    }

    protected void initialize(IViewRule rule, String fqn) {
        rule.onInitialize(fqn, new TestRulesEngine(fqn));
    }

    public static class TestRulesEngine implements IClientRulesEngine {
        private final String mFqn;

        public TestRulesEngine(String fqn) {
            mFqn = fqn;
        }

        @Override
        public void debugPrintf(@NonNull String msg, Object... params) {
            fail("Not supported in tests yet");
        }

        @Override
        public void displayAlert(@NonNull String message) {
            fail("Not supported in tests yet");
        }

        @Override
        public String displayInput(@NonNull String message, @Nullable String value,
                @Nullable IValidator filter) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public @NonNull String getFqcn() {
            return mFqn;
        }

        @Override
        public @NonNull IViewMetadata getMetadata(final @NonNull String fqcn) {
            return new IViewMetadata() {
                @Override
                public @NonNull String getDisplayName() {
                    // This also works when there is no "."
                    return fqcn.substring(fqcn.lastIndexOf('.') + 1);
                }

                @Override
                public @NonNull FillPreference getFillPreference() {
                    return ViewMetadataRepository.get().getFillPreference(fqcn);
                }

                @Override
                public @NonNull Margins getInsets() {
                    return null;
                }

                @Override
                public @NonNull List<String> getTopAttributes() {
                    return ViewMetadataRepository.get().getTopAttributes(fqcn);
                }
            };
        }

        @Override
        public int getMinApiLevel() {
            return 8;
        }

        @Override
        public IViewRule loadRule(@NonNull String fqcn) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public String displayReferenceInput(String currentValue) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public IValidator getResourceValidator(String resourceTypeName, boolean uniqueInProject,
                boolean uniqueInLayout, boolean exists, String... allowed) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public String displayResourceInput(@NonNull String resourceTypeName,
                @Nullable String currentValue) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public String[] displayMarginInput(@Nullable String all, @Nullable String left,
                @Nullable String right, @Nullable String top, @Nullable String bottom) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public String displayIncludeSourceInput() {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public void select(@NonNull Collection<INode> nodes) {
            fail("Not supported in tests yet");
        }

        @Override
        public String displayFragmentSourceInput() {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public void layout() {
            fail("Not supported in tests yet");
        }

        @Override
        public void redraw() {
            fail("Not supported in tests yet");
        }

        @Override
        public Map<INode, Rect> measureChildren(@NonNull INode parent,
                @Nullable AttributeFilter filter) {
            return null;
        }

        @Override
        public int pxToDp(int px) {
            // Arbitrary conversion
            return px / 3;
        }

        @Override
        public int dpToPx(int dp) {
            // Arbitrary conversion
            return 3 * dp;
        }

        @Override
        public @NonNull String getUniqueId(@NonNull String prefix) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public int screenToLayout(int pixels) {
            fail("Not supported in tests yet");
            return pixels;
        }

        @Override
        public @NonNull String getAppNameSpace() {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public @Nullable Object getViewObject(@NonNull INode node) {
            fail("Not supported in tests yet");
            return null;
        }

        @Override
        public boolean rename(INode node) {
            fail("Not supported in tests yet");
            return false;
        }

        @Override
        @Nullable
        public String displayCustomViewClassInput() {
            fail("Not supported in tests yet");
            return null;
        }
    }

    public void testDummy() {
        // To avoid JUnit warning that this class contains no tests, even though
        // this is an abstract class and JUnit shouldn't try
    }
}
