/*
 * 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.eclipse.adt.internal.editors.layout.gle2;

import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

import java.util.ArrayList;

/** Drag listener for the outline page */
/* package */ class OutlineDragListener implements DragSourceListener {
    private TreeViewer mTreeViewer;
    private OutlinePage mOutlinePage;
    private final ArrayList<SelectionItem> mDragSelection = new ArrayList<SelectionItem>();
    private SimpleElement[] mDragElements;

    public OutlineDragListener(OutlinePage outlinePage, TreeViewer treeViewer) {
        super();
        mOutlinePage = outlinePage;
        mTreeViewer = treeViewer;
    }

    public void dragStart(DragSourceEvent e) {
        Tree tree = mTreeViewer.getTree();

        TreeItem overTreeItem = tree.getItem(new Point(e.x, e.y));
        if (overTreeItem == null) {
            // Not dragging over a tree item
            e.doit = false;
            return;
        }
        CanvasViewInfo over = getViewInfo(overTreeItem);
        if (over == null) {
            e.doit = false;
            return;
        }

        // The selection logic for the outline is much simpler than in the canvas,
        // because for one thing, the tree selection is updated synchronously on mouse
        // down, so it's not possible to start dragging a non-selected item.
        // We also don't deliberately disallow root-element dragging since you can
        // drag it into another form.
        final LayoutCanvas canvas = mOutlinePage.getEditor().getCanvasControl();
        SelectionManager selectionManager = canvas.getSelectionManager();
        TreeItem[] treeSelection = tree.getSelection();
        mDragSelection.clear();
        for (TreeItem item : treeSelection) {
            CanvasViewInfo viewInfo = getViewInfo(item);
            if (viewInfo != null) {
                mDragSelection.add(selectionManager.createSelection(viewInfo));
            }
        }
        SelectionManager.sanitize(mDragSelection);

        e.doit = !mDragSelection.isEmpty();
        int imageCount = mDragSelection.size();
        if (e.doit) {
            mDragElements = SelectionItem.getAsElements(mDragSelection);
            GlobalCanvasDragInfo.getInstance().startDrag(mDragElements,
                    mDragSelection.toArray(new SelectionItem[imageCount]),
                    canvas, new Runnable() {
                        public void run() {
                            canvas.getClipboardSupport().deleteSelection("Remove",
                                    mDragSelection);
                        }
                    });
            return;
        }

        e.detail = DND.DROP_NONE;
    }

    public void dragSetData(DragSourceEvent e) {
        if (TextTransfer.getInstance().isSupportedType(e.dataType)) {
            LayoutCanvas canvas = mOutlinePage.getEditor().getCanvasControl();
            e.data = SelectionItem.getAsText(canvas, mDragSelection);
            return;
        }

        if (SimpleXmlTransfer.getInstance().isSupportedType(e.dataType)) {
            e.data = mDragElements;
            return;
        }

        // otherwise we failed
        e.detail = DND.DROP_NONE;
        e.doit = false;
    }

    public void dragFinished(DragSourceEvent e) {
        // Unregister the dragged data.
        // Clear the selection
        mDragSelection.clear();
        mDragElements = null;
        GlobalCanvasDragInfo.getInstance().stopDrag();
    }

    private CanvasViewInfo getViewInfo(TreeItem item) {
        Object data = item.getData();
        if (data != null) {
            return OutlinePage.getViewInfo(data);
        }

        return null;
    }
}