/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0

   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 org.bodington.applet.components;

import org.bodington.applet.*;
import javax.swing.*;

import java.awt.dnd.*;
import java.beans.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import java.io.*;
import javax.swing.tree.*;
import org.bodington.server.ims.*;

public class PackageFileTree extends javax.swing.JTree 
    implements java.awt.dnd.DragGestureListener, 
                java.awt.dnd.DragSourceListener, 
                java.awt.dnd.DropTargetListener
    {
  /**
   * enables this component to be a dropTarget
   */

  DropTarget dropTarget = null;

  /**
   * enables this component to be a Drag Source
   */
  DragSource dragSource = null;

	String publish_base, publish_page;

	public PackageFileTree()
		{
		dropTarget = new DropTarget (this, this);
		dragSource = new DragSource();
		dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY_OR_MOVE, this);

          setRootVisible( false );
          setShowsRootHandles( true );
		}

	public PackageFileTree( TreeModel model, String publish_base, String publish_page )
	    {
	    this();
	    setModel( model );
	    this.publish_base = publish_base;
	    this.publish_page = publish_page;
	    }


    public void dragDropEnd(DragSourceDropEvent dsde)
    {
        // This method is derived from interface java.awt.dnd.DragSourceListener
        // to do: code goes here
    }

    public void dragEnter(DropTargetDragEvent dtde)
        {
        System.out.println( "public void dragEnter(DropTargetDragEvent dtde)" );
        dtde.acceptDrag( DnDConstants.ACTION_COPY );
        }

    public void dragEnter(DragSourceDragEvent dsde)
    {
        // This method is derived from interface java.awt.dnd.DragSourceListener
        // to do: code goes here
    }

    public void dragExit(DropTargetEvent dte)
    {
        // This method is derived from interface java.awt.dnd.DropTargetListener
        // to do: code goes here
    }

    public void dragExit(DragSourceEvent dse)
    {
        // This method is derived from interface java.awt.dnd.DragSourceListener
        // to do: code goes here
    }

    public void dragGestureRecognized(DragGestureEvent event)
    {
    Point p = event.getDragOrigin();
	 TreePath sourcepath = getPathForLocation( p.x, p.y );
	 PackageFileSystemNode sourcenode;
	 PackageFile pf;
	 PackageResource res;
	 
    if ( sourcepath != null )
   	{
		sourcenode = (PackageFileSystemNode)sourcepath.getLastPathComponent();
		pf = sourcenode.getPackageFile();
        if ( pf != null )
            {
            res = (PackageResource)pf.getParent();
            if ( res.getHref().equals( pf.getHref() ) )
                {
                System.out.println( "Starting drag..." );
                dragSource.startDrag(event, DragSource.DefaultMoveDrop, (Transferable)res, this);
                }
            }
   	}
   else
   	{
      System.out.println( "nothing was selected");   
   	}
    }

    public void dragOver(DragSourceDragEvent dsde)
    {
        // This method is derived from interface java.awt.dnd.DragSourceListener
        // to do: code goes here
    }

    public void dragOver(DropTargetDragEvent dtde)
        {
        dtde.acceptDrag(DnDConstants.ACTION_COPY);
        // This method is derived from interface java.awt.dnd.DropTargetListener
        // to do: code goes here
        }

		public void transferTree( TransferLocalFileDialog dialog, File base, File publish )
			throws IOException, MalformedURLException
			{
			// transfer the file first, if it is a file
			if ( publish.isFile() )
				{
				String base_abs = base.getAbsolutePath();
				String publish_abs = publish.getAbsoluteFile().getParent();
				
				if ( base_abs.length() > publish_abs.length() )
					throw new IOException( "Can't upload file outside of selected package folder." );

				String relative;	
				
				if ( base_abs.length() < publish_abs.length() )
					relative = URLEncoder.encode( publish_abs.substring( base_abs.length()+1 ) ) + "/";
				else
					relative = "";
					
				System.out.println( "Relative destination folder on server: " + relative );
				System.out.println( "Absolute base URL: " + publish_base );
				
				URL publish_page_url = new URL(	publish_base + relative + publish_page   );
				
				System.out.println( "Uploading" );
				System.out.println( publish.getAbsolutePath() );
				System.out.println( "to" );
				System.out.println( publish_page_url.toExternalForm() );
				
				dialog.transfer( publish, null, publish_page_url );
				}
			
			// transfer contained file if there are any
			File[] filelist = publish.listFiles();
			for ( int i=0; filelist!=null && i<filelist.length; i++ )
				transferTree( dialog, base, filelist[i] );

			}
			
    public void drop(DropTargetDropEvent event)
        {
	System.out.println( "Drop requested" );

	try
		{
		Transferable transferable = event.getTransferable();
		Point p = event.getLocation();
		TreePath targetpath;
		Rectangle targetbox;
		PackageFile targetnode;
		DefaultTreeModel model = (DefaultTreeModel)getModel();
		int position;


		
		// we accept only    FilePublishRequest.filePublishRequestFlavor
		if (transferable.isDataFlavorSupported( FilePublishRequest.filePublishRequestFlavor ) )
			{
			System.out.println( "FilePublishRequest dropped" );
			FilePublishRequest request =(FilePublishRequest)transferable.getTransferData( 
																FilePublishRequest.filePublishRequestFlavor );
			
			if ( !request.publish.exists() )
				{
				System.out.println( "Dragged file doesn't exist." );
				event.rejectDrop();
				return;
				}

			event.acceptDrop( DnDConstants.ACTION_COPY );

			try
				{
				System.out.println( "Uploading " + request.publish );
				TransferLocalFileDialog t_dialog = new TransferLocalFileDialog( BodingtonDesktopPane.findInstance( this ) );
				
				// recursively publish stuff
				transferTree( t_dialog, request.base, request.publish );
				}
			catch ( Exception ex )
				{
				ex.printStackTrace();
				}

			event.getDropTargetContext().dropComplete(true);
			return;
			}
		
		System.out.println( "Drop rejected" );
		event.rejectDrop();
		}
	catch (IOException exception)
		{
		exception.printStackTrace();
		System.err.println( "Exception" + exception.getMessage());
		event.rejectDrop();
		} 
	catch (UnsupportedFlavorException ufException )
		{
		ufException.printStackTrace();
		System.err.println( "Exception" + ufException.getMessage());
		event.rejectDrop();
		}   
   }

    public void dropActionChanged(DragSourceDragEvent dsde)
    {
        // This method is derived from interface java.awt.dnd.DragSourceListener
        // to do: code goes here
    }

    public void dropActionChanged(DropTargetDragEvent dtde)
    {
        // This method is derived from interface java.awt.dnd.DropTargetListener
        // to do: code goes here
    }

}
