/*
* Copyright (c) 1997 - 2016
* Actelion Pharmaceuticals Ltd.
* Gewerbestrasse 16
* CH-4123 Allschwil, Switzerland
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
*    list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
* 3. Neither the name of the the copyright holder nor the
*    names of its contributors may be used to endorse or promote products
*    derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

package com.actelion.research.gui.dnd;

import com.actelion.research.chem.AbstractDepictor;
import com.actelion.research.chem.Depictor2D;
import com.actelion.research.chem.StereoMolecule;
import com.actelion.research.chem.dnd.ChemistryFlavors;

import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;


public abstract class MoleculeDragAdapter implements DragSourceListener//,DragSourceMotionListener
{
    int mAllowedDragAction;
    Cursor cursor = null;

    public MoleculeDragAdapter(Component c)
    {
//        DragSource ds = new DragSource();
//        ds.addDragSourceListener(new WindowMovingDragSourceListener());

        DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
            c, DnDConstants.ACTION_COPY_OR_MOVE, new DGListener());
        mAllowedDragAction = DnDConstants.ACTION_COPY_OR_MOVE;
    }

    public void allowDrag(boolean allow)
    {
        if (allow)
            mAllowedDragAction = DnDConstants.ACTION_COPY_OR_MOVE;
        else
            mAllowedDragAction = DnDConstants.ACTION_NONE;
    }

    public abstract Transferable getTransferable(Point origin);

    public void onDragEnter()
    {

    }

    public void onDragOver()
    {

    }

    public void onDragExit()
    {

    }

    public void dragDropEnd(DragSourceDropEvent e)
    {
    }

    public final void dragEnter(DragSourceDragEvent e)
    {
        DragSourceContext context = e.getDragSourceContext();
        int dropAction = e.getDropAction();
        if ((dropAction & mAllowedDragAction) != 0) {
//            if (cursor != null)
//                context.setCursor(cursor);
//            else
                context.setCursor(DragSource.DefaultCopyDrop);
        } else {
            context.setCursor(DragSource.DefaultCopyNoDrop);
        }
        onDragEnter();
    }

    public final void dragOver(DragSourceDragEvent e)
    {
        onDragOver();
    }

    public final void dragExit(DragSourceEvent e)
    {
        onDragExit();
    }

    public final void dropActionChanged(DragSourceDragEvent e)
    {
        DragSourceContext context = e.getDragSourceContext();
        int dropAction = e.getDropAction();
        if ((dropAction & mAllowedDragAction) != 0) {
//            if (cursor != null)
//                context.setCursor(cursor);
//            else
                context.setCursor(DragSource.DefaultCopyDrop);
        } else {
            context.setCursor(DragSource.DefaultCopyNoDrop);
        }
    }


//    class WindowMovingDragSourceListener extends DragSourceAdapter implements DragSourceMotionListener {
//
//        private Window win;
//        private boolean firstCall = true;
//
//        public WindowMovingDragSourceListener(Window w) {
//            win = w;
//        }
//
//        public void dragDropEnd(DragSourceDropEvent dsde) {
//            System.err.println("dragDropEnd(): " + dsde);
//            win.setVisible(false);
//            firstCall = true;
//        }
//
//        public void dragMouseMoved(DragSourceDragEvent dsde) {
//            Point p = dsde.getLocation();
//            p.translate(32, 16);
//            win.setLocation(p);
//            if (firstCall) {
//                win.setVisible(true);
//                firstCall = false;
//            }
//        }
//    }

    class DGListener implements DragGestureListener
    {
        public void dragGestureRecognized(DragGestureEvent e)
        {
            onDragBegin(e);
        }

    }


    protected void onDragBegin(DragGestureEvent e)
    {
        cursor = null;
        if ((e.getDragAction() & mAllowedDragAction) != 0) {
            Transferable transferable = getTransferable(e.getDragOrigin());
            if (transferable != null) {
                try {
                    Image img = null;
                    if (DragSource.isDragImageSupported() && (img = drawDragImage(transferable,400,400)) != null) {
                        e.startDrag(DragSource.DefaultCopyDrop, img, new Point(200, 200), transferable, this);
                    } else {
                        e.startDrag(cursor, transferable, this);
                    }
                    dragIsValidAndStarts();
                } catch (InvalidDnDOperationException idoe) {
                    System.err.println(idoe);
                }
            }
        }
    }

    public Image drawDragImage(Transferable transferable,int width,int height)
    {
        if (transferable instanceof MoleculeTransferable) {
            try {
                MoleculeTransferable t = (MoleculeTransferable) transferable;
                Object o = t.getTransferData(ChemistryFlavors.DF_SERIALIZED_MOLECULE);
                if (o instanceof StereoMolecule) {
                    StereoMolecule mol = (StereoMolecule) o;
                    Depictor2D depict = new Depictor2D(mol);
                    BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g = (Graphics2D)img.getGraphics();
                    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    		        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
                    depict.validateView(g, new Rectangle2D.Double(0, 0, width, height), AbstractDepictor.cModeInflateToMaxAVBL);
                    depict.paint(g);
                    return img;
                }
            } catch (IOException e1) {
                System.err.println(e1);
            } catch (UnsupportedFlavorException e1) {
                System.err.println(e1);
            }
        }
        return null;
    }

    // may be overridden
    public void dragIsValidAndStarts() {}


//    final Window w = new Window() {
//                public void paint(Graphics g) {
//                    g.drawString("image", 5, 20); // or render an image via g.drawImage()
//                }
//            };

}
