/*
 * 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 <wtf/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;
struct PromisedAttachmentInfo;

    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; }
        DragHandlingMethod dragHandlingMethod() const { return m_dragHandlingMethod; }

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

        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)
        PromisedAttachmentInfo promisedAttachmentInfo(Frame&, Element&);
#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 { DragHandlingMethod::None };

        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
