/*
 * Copyright (C) 2011 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.eclipse.adt.internal.editors.layout.gle2;

import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.ResizePolicy;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionHandle.Position;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * The {@link SelectionHandles} of a {@link SelectionItem} are the set of
 * {@link SelectionHandle} objects (possibly empty, for non-resizable objects) the user
 * can manipulate to resize a widget.
 */
public class SelectionHandles implements Iterable<SelectionHandle> {
    private final SelectionItem mItem;
    private List<SelectionHandle> mHandles;

    /**
     * Constructs a new {@link SelectionHandles} object for the given {link
     * {@link SelectionItem}
     * @param item the item to create {@link SelectionHandles} for
     */
    public SelectionHandles(SelectionItem item) {
        mItem = item;

        createHandles(item.getCanvas());
    }

    /**
     * Find a specific {@link SelectionHandle} from this set of {@link SelectionHandles},
     * which is within the given distance (in layout coordinates) from the center of the
     * {@link SelectionHandle}.
     *
     * @param point the mouse position (in layout coordinates) to test
     * @param distance the maximum distance from the handle center to accept
     * @return a {@link SelectionHandle} under the point, or null if not found
     */
    public SelectionHandle findHandle(LayoutPoint point, int distance) {
        for (SelectionHandle handle : mHandles) {
            if (handle.contains(point, distance)) {
                return handle;
            }
        }

        return null;
    }

    /**
     * Create the {@link SelectionHandle} objects for the selection item, according to its
     * {@link ResizePolicy}.
     */
    private void createHandles(LayoutCanvas canvas) {
        NodeProxy selectedNode = mItem.getNode();
        Rect r = selectedNode.getBounds();
        if (!r.isValid()) {
            mHandles = Collections.emptyList();
            return;
        }

        ResizePolicy resizability = mItem.getResizePolicy();
        if (resizability.isResizable()) {
            mHandles = new ArrayList<SelectionHandle>(8);
            boolean left = resizability.leftAllowed();
            boolean right = resizability.rightAllowed();
            boolean top = resizability.topAllowed();
            boolean bottom = resizability.bottomAllowed();
            int x1 = r.x;
            int y1 = r.y;
            int w = r.w;
            int h = r.h;
            int x2 = x1 + w;
            int y2 = y1 + h;

            Margins insets = canvas.getInsets(mItem.getNode().getFqcn());
            if (insets != null) {
                x1 += insets.left;
                x2 -= insets.right;
                y1 += insets.top;
                y2 -= insets.bottom;
            }

            int mx = (x1 + x2) / 2;
            int my = (y1 + y2) / 2;

            if (left) {
                mHandles.add(new SelectionHandle(x1, my, Position.LEFT_MIDDLE));
                if (top) {
                    mHandles.add(new SelectionHandle(x1, y1, Position.TOP_LEFT));
                }
                if (bottom) {
                    mHandles.add(new SelectionHandle(x1, y2, Position.BOTTOM_LEFT));
                }
            }
            if (right) {
                mHandles.add(new SelectionHandle(x2, my, Position.RIGHT_MIDDLE));
                if (top) {
                    mHandles.add(new SelectionHandle(x2, y1, Position.TOP_RIGHT));
                }
                if (bottom) {
                    mHandles.add(new SelectionHandle(x2, y2, Position.BOTTOM_RIGHT));
                }
            }
            if (top) {
                mHandles.add(new SelectionHandle(mx, y1, Position.TOP_MIDDLE));
            }
            if (bottom) {
                mHandles.add(new SelectionHandle(mx, y2, Position.BOTTOM_MIDDLE));
            }
        } else {
            mHandles = Collections.emptyList();
        }
    }

    // Implements Iterable<SelectionHandle>
    public Iterator<SelectionHandle> iterator() {
        return mHandles.iterator();
    }
}
