/*
 * 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.
 *
 * @author Christian Rufener
 */

package com.actelion.research.gui.dnd;

import com.actelion.research.chem.AbstractDepictor;
import com.actelion.research.chem.ExtendedDepictor;
import com.actelion.research.chem.dnd.ChemistryFlavors;
import com.actelion.research.chem.reaction.Reaction;
import com.actelion.research.gui.generic.GenericRectangle;
import com.actelion.research.gui.swing.SwingDrawContext;

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


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

	public ReactionDragAdapter(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 final 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);
					}
				} catch (InvalidDnDOperationException idoe) {
					System.err.println(idoe);
				}
			}
		}
	}

	public Image drawDragImage(Transferable transferable,int width,int height) {
		if (transferable instanceof ReactionTransferable) {
			try {
				MoleculeTransferable t = (MoleculeTransferable) transferable;
				Object o = t.getTransferData(ChemistryFlavors.DF_SERIALIZED_REACTION);
				if (o instanceof Reaction) {
					Reaction rxn = (Reaction) o;
					ExtendedDepictor depict = new ExtendedDepictor(rxn, null, false);
					BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
					Graphics g = img.getGraphics();
					((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
					((Graphics2D)g).setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
					SwingDrawContext context = new SwingDrawContext((Graphics2D)g);
					depict.validateView(context, new GenericRectangle(0, 0, width, height), AbstractDepictor.cModeInflateToMaxAVBL);
					depict.paint(context);
					return img;
				}
			} catch (IOException e1) {
				System.err.println(e1);
			} catch (UnsupportedFlavorException e1) {
				System.err.println(e1);
			}
		}
		return null;
	}


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

}
