/*
 * Copyright (C) 2007, 2009 Apple Inc. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. 
 */

#pragma once

#include "DragActions.h"
#include "DragImage.h"
#include "IntPoint.h"
#include "IntRect.h"
#include "URL.h"

namespace WebCore {

class DataTransfer;
class Document;
class DragClient;
class DragData;
class Element;
class Frame;
class FrameSelection;
class HTMLInputElement;
class IntRect;
class Page;
class PlatformMouseEvent;

struct DragItem;
struct DragState;

    class DragController {
        WTF_MAKE_NONCOPYABLE(DragController); WTF_MAKE_FAST_ALLOCATED;
    public:
        DragController(Page&, DragClient&);
        ~DragController();

        static std::unique_ptr<DragController> create(Page&, DragClient&);

        DragClient& client() const { return m_client; }

        WEBCORE_EXPORT DragOperation dragEntered(const DragData&);
        WEBCORE_EXPORT void dragExited(const DragData&);
        WEBCORE_EXPORT DragOperation dragUpdated(const DragData&);
        WEBCORE_EXPORT bool performDragOperation(const DragData&);
        WEBCORE_EXPORT void dragCancelled();

        bool mouseIsOverFileInput() const { return m_fileInputElementUnderMouse; }
        unsigned numberOfItemsToBeAccepted() const { return m_numberOfItemsToBeAccepted; }

        // FIXME: It should be possible to remove a number of these accessors once all
        // drag logic is in WebCore.
        void setDidInitiateDrag(bool initiated) { m_didInitiateDrag = initiated; } 
        bool didInitiateDrag() const { return m_didInitiateDrag; }
        DragOperation sourceDragOperation() const { return m_sourceDragOperation; }
        const URL& draggingImageURL() const { return m_draggingImageURL; }
#if ENABLE(ATTACHMENT_ELEMENT)
        const URL& draggingAttachmentURL() const { return m_draggingAttachmentURL; }
#endif
        void setDragOffset(const IntPoint& offset) { m_dragOffset = offset; }
        const IntPoint& dragOffset() const { return m_dragOffset; }
        DragSourceAction dragSourceAction() const { return m_dragSourceAction; }

        enum class DragHandlingMethod { None, EditPlainText, EditRichText, UploadFile, PageLoad, SetColor, NonDefault };
        Document* documentUnderMouse() const { return m_documentUnderMouse.get(); }
        DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; }
        DragSourceAction delegateDragSourceAction(const IntPoint& rootViewPoint);
        
        Element* draggableElement(const Frame*, Element* start, const IntPoint&, DragState&) const;
        WEBCORE_EXPORT void dragEnded();
        
        WEBCORE_EXPORT void placeDragCaret(const IntPoint&);
        
        bool startDrag(Frame& src, const DragState&, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin);
        static const IntSize& maxDragImageSize();
        
        static const int MaxOriginalImageArea;
        static const int DragIconRightInset;
        static const int DragIconBottomInset;        
        static const float DragImageAlpha;

    private:
        void updateSupportedTypeIdentifiersForDragHandlingMethod(DragHandlingMethod, const DragData&) const;
        bool dispatchTextInputEventFor(Frame*, const DragData&);
        bool canProcessDrag(const DragData&);
        bool concludeEditDrag(const DragData&);
        DragOperation dragEnteredOrUpdated(const DragData&);
        DragOperation operationForLoad(const DragData&);
        DragHandlingMethod tryDocumentDrag(const DragData&, DragDestinationAction, DragOperation&);
        bool tryDHTMLDrag(const DragData&, DragOperation&);
        DragOperation dragOperation(const DragData&);
        void clearDragCaret();
        bool dragIsMove(FrameSelection&, const DragData&);
        bool isCopyKeyDown(const DragData&);

        void mouseMovedIntoDocument(Document*);
        bool shouldUseCachedImageForDragImage(const Image&) const;

        void doImageDrag(Element&, const IntPoint&, const IntRect&, DataTransfer&, Frame&, IntPoint&);
        void doSystemDrag(DragImage, const IntPoint&, const IntPoint&, const IntRect& dragImageBounds, DataTransfer&, Frame&, DragSourceAction);

        void beginDrag(DragItem, Frame&, const IntPoint& mouseDownPoint, const IntPoint& mouseDraggedPoint, DataTransfer&, DragSourceAction);

        bool canLoadDataFromDraggingPasteboard() const
        {
#if ENABLE(DATA_INTERACTION)
            return m_isPerformingDrop;
#else
            return true;
#endif
        }

        void cleanupAfterSystemDrag();
        void declareAndWriteDragImage(DataTransfer&, Element&, const URL&, const String& label);
#if ENABLE(ATTACHMENT_ELEMENT)
        void declareAndWriteAttachment(DataTransfer&, Element&, const URL&);
#endif
        Page& m_page;
        DragClient& m_client;

        RefPtr<Document> m_documentUnderMouse; // The document the mouse was last dragged over.
        RefPtr<Document> m_dragInitiator; // The Document (if any) that initiated the drag.
        RefPtr<HTMLInputElement> m_fileInputElementUnderMouse;
        unsigned m_numberOfItemsToBeAccepted;
        DragHandlingMethod m_dragHandlingMethod;

        DragDestinationAction m_dragDestinationAction;
        DragSourceAction m_dragSourceAction;
        bool m_didInitiateDrag;
        DragOperation m_sourceDragOperation; // Set in startDrag when a drag starts from a mouse down within WebKit
        IntPoint m_dragOffset;
        URL m_draggingImageURL;
        bool m_isPerformingDrop { false };
#if ENABLE(ATTACHMENT_ELEMENT)
        URL m_draggingAttachmentURL;
#endif
    };

    WEBCORE_EXPORT bool isDraggableLink(const Element&);

} // namespace WebCore
