/*
 * 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 HTMLAttachmentElement;
class HTMLInputElement;
class IntRect;
class Page;
class PlatformMouseEvent;

struct DragItem;
struct DragState;
struct PromisedBlobInfo;

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

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

        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; }
        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, HasNonDefaultPasteboardData);
        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&, Frame&, IntPoint&, const DragState&);
        void doSystemDrag(DragImage, const IntPoint&, const IntPoint&, Frame&, const DragState&, PromisedBlobInfo&&);

        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
        }

        String platformContentTypeForBlobType(const String& type) const;

        void cleanupAfterSystemDrag();
        void declareAndWriteDragImage(DataTransfer&, Element&, const URL&, const String& label);

#if ENABLE(ATTACHMENT_ELEMENT)
        PromisedBlobInfo promisedBlobInfo(Frame&, HTMLAttachmentElement&);
#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 };
    };

    WEBCORE_EXPORT bool isDraggableLink(const Element&);

} // namespace WebCore
