/*
 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package sun.lwawt.macosx;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.image.*;

import javax.swing.*;
import javax.swing.text.*;
import javax.accessibility.*;

import java.util.Map;
import java.util.concurrent.Callable;

import sun.awt.AWTAccessor;
import sun.awt.dnd.*;
import sun.lwawt.LWComponentPeer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformWindow;


public final class CDragSourceContextPeer extends SunDragSourceContextPeer {

    private static final CDragSourceContextPeer fInstance = new CDragSourceContextPeer(null);

    private Image  fDragImage;
    private CImage fDragCImage;
    private Point  fDragImageOffset;

    private static Component hoveringComponent = null;

    private static double fMaxImageSize = 128.0;

    static {
        String propValue = java.security.AccessController.doPrivileged(new sun.security.action.GetPropertyAction("apple.awt.dnd.defaultDragImageSize"));
        if (propValue != null) {
            try {
                double value = Double.parseDouble(propValue);
                if (value > 0) {
                    fMaxImageSize = value;
                }
            } catch(NumberFormatException e) {}
        }
    }

    private CDragSourceContextPeer(DragGestureEvent dge) {
        super(dge);
    }

    public static CDragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
        fInstance.setTrigger(dge);

        return fInstance;
    }

    // We have to overload this method just to be able to grab the drag image and its offset as shared code doesn't store it:
    public void startDrag(DragSourceContext dsc, Cursor cursor, Image dragImage, Point dragImageOffset) throws InvalidDnDOperationException {
        fDragImage = dragImage;
        fDragImageOffset = dragImageOffset;

        super.startDrag(dsc, cursor, dragImage, dragImageOffset);
    }

    protected void startDrag(Transferable transferable, long[] formats, Map<Long, DataFlavor> formatMap) {
        DragGestureEvent trigger = getTrigger();
        InputEvent         triggerEvent = trigger.getTriggerEvent();

        Point dragOrigin = new Point(trigger.getDragOrigin());
        int extModifiers = (triggerEvent.getModifiers() | triggerEvent.getModifiersEx());
        long timestamp   = triggerEvent.getWhen();
        int clickCount   = ((triggerEvent instanceof MouseEvent) ? (((MouseEvent) triggerEvent).getClickCount()) : 1);

        Component component = trigger.getComponent();
        // For a lightweight component traverse up the hierarchy to the root
        Point loc = component.getLocation();
        Component rootComponent = component;
        while (!(rootComponent instanceof Window)) {
            dragOrigin.translate(loc.x, loc.y);
            rootComponent = rootComponent.getParent();
            loc = rootComponent.getLocation();
        }

        // If there isn't any drag image make one of default appearance:
        if (fDragImage == null)
            this.setDefaultDragImage(component);

        // Get drag image (if any) as BufferedImage and convert that to CImage:
        Point dragImageOffset;

        if (fDragImage != null) {
            try {
                fDragCImage = CImage.getCreator().createFromImageImmediately(fDragImage);
            } catch(Exception e) {
                // image creation may fail for any reason
                throw new InvalidDnDOperationException("Drag image can not be created.");
            }
            if (fDragCImage == null) {
                throw new InvalidDnDOperationException("Drag image is not ready.");
            }

            dragImageOffset = fDragImageOffset;
        } else {

            fDragCImage = null;
            dragImageOffset = new Point(0, 0);
        }

        try {
            //It sure will be LWComponentPeer instance as rootComponent is a Window
            LWComponentPeer<?, ?> peer = AWTAccessor.getComponentAccessor()
                                                    .getPeer(rootComponent);
            PlatformWindow platformWindow = peer.getPlatformWindow();
            long nativeViewPtr = CPlatformWindow.getNativeViewPtr(platformWindow);
            if (nativeViewPtr == 0L) throw new InvalidDnDOperationException("Unsupported platform window implementation");

            // Create native dragging source:
            final long nativeDragSource = createNativeDragSource(component, nativeViewPtr, transferable, triggerEvent,
                (int) (dragOrigin.getX()), (int) (dragOrigin.getY()), extModifiers,
                clickCount, timestamp, fDragCImage != null ? fDragCImage.ptr : 0L, dragImageOffset.x, dragImageOffset.y,
                getDragSourceContext().getSourceActions(), formats, formatMap);

            if (nativeDragSource == 0)
                throw new InvalidDnDOperationException("");

            setNativeContext(nativeDragSource);
        }

        catch (Exception e) {
            throw new InvalidDnDOperationException("failed to create native peer: " + e);
        }

        SunDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(transferable);

        CCursorManager.getInstance().setCursor(getCursor());

        // Create a new thread to run the dragging operation since it's synchronous, only coming back
        // after dragging is finished. This leaves the AWT event thread free to handle AWT events which
        // are posted during dragging by native event handlers.

        try {
            Runnable dragRunnable = () -> {
                final long nativeDragSource = getNativeContext();
                try {
                    doDragging(nativeDragSource);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    releaseNativeDragSource(nativeDragSource);
                    fDragImage = null;
                    if (fDragCImage != null) {
                        fDragCImage.dispose();
                        fDragCImage = null;
                    }
                }
            };
            new Thread(null, dragRunnable, "Drag", 0, false).start();
        } catch (Exception e) {
            final long nativeDragSource = getNativeContext();
            setNativeContext(0);
            releaseNativeDragSource(nativeDragSource);
            SunDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(null);
            throw new InvalidDnDOperationException("failed to start dragging thread: " + e);
        }
    }

    private void setDefaultDragImage(Component component) {
        boolean handled = false;

        // Special-case default drag image, depending on the drag source type:
        if (component.isLightweight()) {
            if (component instanceof JTextComponent) {
                this.setDefaultDragImage((JTextComponent) component);
                handled = true;
            } else if (component instanceof JTree) {
                            this.setDefaultDragImage((JTree) component);
                            handled = true;
                        } else if (component instanceof JTable) {
                            this.setDefaultDragImage((JTable) component);
                            handled = true;
                        } else if (component instanceof JList) {
                            this.setDefaultDragImage((JList) component);
                            handled = true;
                        }
        }

        if (handled == false)
            this.setDefaultDragImage();
    }

    @SuppressWarnings("deprecation")
    private void setDefaultDragImage(JTextComponent component) {
        DragGestureEvent trigger = getTrigger();
        int selectionStart = component.getSelectionStart();
        int selectionEnd = component.getSelectionEnd();
        boolean handled = false;

        // Make sure we're dragging current selection:
        int index = component.viewToModel(trigger.getDragOrigin());
        if ((selectionStart < selectionEnd) && (index >= selectionStart) && (index <= selectionEnd)) {
            try {
                Rectangle selectionStartBounds = component.modelToView(selectionStart);
                Rectangle selectionEndBounds = component.modelToView(selectionEnd);

                Rectangle selectionBounds = null;

                // Single-line selection:
                if (selectionStartBounds.y == selectionEndBounds.y) {
                    selectionBounds = new Rectangle(selectionStartBounds.x, selectionStartBounds.y,
                        selectionEndBounds.x - selectionStartBounds.x + selectionEndBounds.width,
                        selectionEndBounds.y - selectionStartBounds.y + selectionEndBounds.height);
                }

                // Multi-line selection:
                else {
                    AccessibleContext ctx = component.getAccessibleContext();
                    AccessibleText at = (AccessibleText) ctx;

                    selectionBounds = component.modelToView(selectionStart);
                    for (int i = selectionStart + 1; i <= selectionEnd; i++) {
                                            Rectangle charBounds = at.getCharacterBounds(i);
                                            // Invalid index returns null Rectangle
                                            // Note that this goes against jdk doc - should be empty, but is null instead
                                            if (charBounds != null) {
                                                selectionBounds.add(charBounds);
                                            }
                    }
                }

                this.setOutlineDragImage(selectionBounds);
                handled = true;
            }

            catch (BadLocationException exc) {
                // Default the drag image to component bounds.
            }
        }

        if (handled == false)
            this.setDefaultDragImage();
    }


    private void setDefaultDragImage(JTree component) {
        Rectangle selectedOutline = null;

        int[] selectedRows = component.getSelectionRows();
        for (int i=0; i<selectedRows.length; i++) {
            Rectangle r = component.getRowBounds(selectedRows[i]);
            if (selectedOutline == null)
                selectedOutline = r;
            else
                selectedOutline.add(r);
        }

        if (selectedOutline != null) {
            this.setOutlineDragImage(selectedOutline);
        } else {
            this.setDefaultDragImage();
        }
    }

    private void setDefaultDragImage(JTable component) {
        Rectangle selectedOutline = null;

        // This code will likely break once multiple selections works (3645873)
        int[] selectedRows = component.getSelectedRows();
        int[] selectedColumns = component.getSelectedColumns();
        for (int row=0; row<selectedRows.length; row++) {
            for (int col=0; col<selectedColumns.length; col++) {
                Rectangle r = component.getCellRect(selectedRows[row], selectedColumns[col], true);
                if (selectedOutline == null)
                    selectedOutline = r;
                else
                    selectedOutline.add(r);
            }
        }

        if (selectedOutline != null) {
            this.setOutlineDragImage(selectedOutline);
        } else {
            this.setDefaultDragImage();
        }
    }

    private void setDefaultDragImage(JList<?> component) {
        Rectangle selectedOutline = null;

        // This code actually works, even under the (non-existant) multiple-selections, because we only draw a union outline
        int[] selectedIndices = component.getSelectedIndices();
        if (selectedIndices.length > 0)
            selectedOutline = component.getCellBounds(selectedIndices[0], selectedIndices[selectedIndices.length-1]);

        if (selectedOutline != null) {
            this.setOutlineDragImage(selectedOutline);
        } else {
            this.setDefaultDragImage();
        }
    }


    private void setDefaultDragImage() {
        DragGestureEvent trigger = this.getTrigger();
        Component comp = trigger.getComponent();

        setOutlineDragImage(new Rectangle(0, 0, comp.getWidth(), comp.getHeight()), true);
    }

    private void setOutlineDragImage(Rectangle outline) {
        setOutlineDragImage(outline, false);
    }

    private void setOutlineDragImage(Rectangle outline, Boolean shouldScale) {
        int width = (int)outline.getWidth();
        int height = (int)outline.getHeight();

        double scale = 1.0;
        if (shouldScale) {
            final int area = width * height;
            final int maxArea = (int)(fMaxImageSize * fMaxImageSize);

            if (area > maxArea) {
                scale = (double)area / (double)maxArea;
                width /= scale;
                height /= scale;
            }
        }

        if (width <=0) width = 1;
        if (height <=0) height = 1;

        DragGestureEvent trigger = this.getTrigger();
        Component comp = trigger.getComponent();
        Point compOffset = comp.getLocation();

        // For lightweight components add some special treatment:
        if (comp instanceof JComponent) {
            // Intersect requested bounds with visible bounds:
            Rectangle visibleBounds = ((JComponent) comp).getVisibleRect();
            Rectangle clipedOutline = outline.intersection(visibleBounds);
            if (clipedOutline.isEmpty() == false)
                outline = clipedOutline;

            // Compensate for the component offset (e.g. when contained in a JScrollPane):
            outline.translate(compOffset.x, compOffset.y);
        }

        GraphicsConfiguration config = comp.getGraphicsConfiguration();
        BufferedImage dragImage = config.createCompatibleImage(width, height, Transparency.TRANSLUCENT);

        Color paint = Color.gray;
        BasicStroke stroke = new BasicStroke(2.0f);
        int halfLineWidth = (int) (stroke.getLineWidth() + 1) / 2; // Rounded up.

        Graphics2D g2 = (Graphics2D) dragImage.getGraphics();
        g2.setPaint(paint);
        g2.setStroke(stroke);
        g2.drawRect(halfLineWidth, halfLineWidth, width - 2 * halfLineWidth - 1, height - 2 * halfLineWidth - 1);
        g2.dispose();

        fDragImage = dragImage;


        Point dragOrigin = trigger.getDragOrigin();
        Point dragImageOffset = new Point(outline.x - dragOrigin.x, outline.y - dragOrigin.y);
        if (comp instanceof JComponent) {
            dragImageOffset.translate(-compOffset.x, -compOffset.y);
        }

        if (shouldScale) {
            dragImageOffset.x /= scale;
            dragImageOffset.y /= scale;
        }

        fDragImageOffset = dragImageOffset;
    }

    /**
     * upcall from native code
     */
    private void dragMouseMoved(final int targetActions,
                                final int modifiers,
                                final int x, final int y) {

        try {
            Component componentAt = LWCToolkit.invokeAndWait(
                    new Callable<Component>() {
                        @Override
                        public Component call() {
                            LWWindowPeer mouseEventComponent = LWWindowPeer.getWindowUnderCursor();
                            if (mouseEventComponent == null) {
                                return null;
                            }
                            Component root = SwingUtilities.getRoot(mouseEventComponent.getTarget());
                            if (root == null) {
                                return null;
                            }
                            Point rootLocation = root.getLocationOnScreen();
                            return getDropTargetAt(root, x - rootLocation.x, y - rootLocation.y);
                        }
                    }, getComponent());

            if(componentAt != hoveringComponent) {
                if(hoveringComponent != null) {
                    dragExit(x, y);
                }
                if(componentAt != null) {
                    dragEnter(targetActions, modifiers, x, y);
                }
                hoveringComponent = componentAt;
            }

            postDragSourceDragEvent(targetActions, modifiers, x, y,
                    DISPATCH_MOUSE_MOVED);
        } catch (Exception e) {
            throw new InvalidDnDOperationException("Failed to handle DragMouseMoved event");
        }
    }

    //Returns the first lightweight or heavyweight Component which has a dropTarget ready to accept the drag
    //Should be called from the EventDispatchThread
    private static Component getDropTargetAt(Component root, int x, int y) {
        if (!root.contains(x, y) || !root.isEnabled() || !root.isVisible()) {
            return null;
        }

        if (root.getDropTarget() != null && root.getDropTarget().isActive()) {
            return root;
        }

        if (root instanceof Container) {
            for (Component comp : ((Container) root).getComponents()) {
                Point loc = comp.getLocation();
                Component dropTarget = getDropTargetAt(comp, x - loc.x, y - loc.y);
                if (dropTarget != null) {
                    return dropTarget;
                }
            }
        }

        return null;
    }

    /**
     * upcall from native code - reset hovering component
     */
    private void resetHovering() {
        hoveringComponent = null;
    }

    @Override
    protected void setNativeCursor(long nativeCtxt, Cursor c, int cType) {
        CCursorManager.getInstance().setCursor(c);
    }

    // Native support:
    private native long createNativeDragSource(Component component, long nativePeer, Transferable transferable,
        InputEvent triggerEvent, int dragPosX, int dragPosY, int extModifiers, int clickCount, long timestamp,
        long nsDragImagePtr, int dragImageOffsetX, int dragImageOffsetY,
        int sourceActions, long[] formats, Map<Long, DataFlavor> formatMap);

    private native void doDragging(long nativeDragSource);

    private native void releaseNativeDragSource(long nativeDragSource);
}
