/*
 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
 * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef Event_h
#define Event_h

#include "Clipboard.h"
#include "DOMTimeStamp.h"
#include <wtf/RefCounted.h>
#include <wtf/text/AtomicString.h>

namespace WebCore {

    class EventTarget;
    class EventDispatcher;

    class Event : public RefCounted<Event> {
    public:
        enum PhaseType { 
            CAPTURING_PHASE     = 1, 
            AT_TARGET           = 2,
            BUBBLING_PHASE      = 3 
        };

        enum EventType {
            MOUSEDOWN           = 1,
            MOUSEUP             = 2,
            MOUSEOVER           = 4,
            MOUSEOUT            = 8,
            MOUSEMOVE           = 16,
            MOUSEDRAG           = 32,
            CLICK               = 64,
            DBLCLICK            = 128,
            KEYDOWN             = 256,
            KEYUP               = 512,
            KEYPRESS            = 1024,
            DRAGDROP            = 2048,
            FOCUS               = 4096,
            BLUR                = 8192,
            SELECT              = 16384,
            CHANGE              = 32768
        };

        static PassRefPtr<Event> create()
        {
            return adoptRef(new Event);
        }
        static PassRefPtr<Event> create(const AtomicString& type, bool canBubble, bool cancelable)
        {
            return adoptRef(new Event(type, canBubble, cancelable));
        }
        virtual ~Event();

        void initEvent(const AtomicString& type, bool canBubble, bool cancelable);

        const AtomicString& type() const { return m_type; }
        
        EventTarget* target() const { return m_target.get(); }
        void setTarget(PassRefPtr<EventTarget>);

        EventTarget* currentTarget() const { return m_currentTarget; }
        void setCurrentTarget(EventTarget* currentTarget) { m_currentTarget = currentTarget; }

        unsigned short eventPhase() const { return m_eventPhase; }
        void setEventPhase(unsigned short eventPhase) { m_eventPhase = eventPhase; }

        bool bubbles() const { return m_canBubble; }
        bool cancelable() const { return m_cancelable; }
        DOMTimeStamp timeStamp() const { return m_createTime; }

        void stopPropagation() { m_propagationStopped = true; }
        void stopImmediatePropagation() { m_immediatePropagationStopped = true; }
        
        // IE Extensions
        EventTarget* srcElement() const { return target(); } // MSIE extension - "the object that fired the event"

        bool returnValue() const { return !defaultPrevented(); }
        void setReturnValue(bool returnValue) { setDefaultPrevented(!returnValue); }

        Clipboard* clipboardData() const { return isClipboardEvent() ? clipboard() : 0; }

        virtual bool isCustomEvent() const;
        virtual bool isUIEvent() const;
        virtual bool isMouseEvent() const;
        virtual bool isMutationEvent() const;
        virtual bool isKeyboardEvent() const;
        virtual bool isTextEvent() const;
        virtual bool isCompositionEvent() const;
        virtual bool isDragEvent() const; // a subset of mouse events
        virtual bool isClipboardEvent() const;
        virtual bool isMessageEvent() const;
        virtual bool isWheelEvent() const;
        virtual bool isBeforeTextInsertedEvent() const;
        virtual bool isOverflowEvent() const;
        virtual bool isPageTransitionEvent() const;
        virtual bool isPopStateEvent() const;
        virtual bool isProgressEvent() const;
        virtual bool isXMLHttpRequestProgressEvent() const;
        virtual bool isWebKitAnimationEvent() const;
        virtual bool isWebKitTransitionEvent() const;
        virtual bool isBeforeLoadEvent() const;
        virtual bool isHashChangeEvent() const;
#if ENABLE(SVG)
        virtual bool isSVGZoomEvent() const;
#endif
#if ENABLE(DOM_STORAGE)
        virtual bool isStorageEvent() const;
#endif
#if ENABLE(INDEXED_DATABASE)
        virtual bool isIDBVersionChangeEvent() const;
#endif
#if ENABLE(WEB_AUDIO)
        virtual bool isAudioProcessingEvent() const;
        virtual bool isOfflineAudioCompletionEvent() const;
#endif
        virtual bool isErrorEvent() const;
#if ENABLE(TOUCH_EVENTS)
        virtual bool isTouchEvent() const;
#if PLATFORM(ANDROID)
        virtual bool hitTouchHandler() const { return false; }
        virtual void setHitTouchHandler() { }
#endif
#endif
#if ENABLE(DEVICE_ORIENTATION)
        virtual bool isDeviceMotionEvent() const;
        virtual bool isDeviceOrientationEvent() const;
#endif
#if ENABLE(INPUT_SPEECH)
        virtual bool isSpeechInputEvent() const;
#endif
        bool fromUserGesture();
        
        bool propagationStopped() const { return m_propagationStopped || m_immediatePropagationStopped; }
        bool immediatePropagationStopped() const { return m_immediatePropagationStopped; }

        bool defaultPrevented() const { return m_defaultPrevented; }
        void preventDefault() { if (m_cancelable) m_defaultPrevented = true; }
        void setDefaultPrevented(bool defaultPrevented) { m_defaultPrevented = defaultPrevented; }

        bool defaultHandled() const { return m_defaultHandled; }
        void setDefaultHandled() { m_defaultHandled = true; }

        bool cancelBubble() const { return m_cancelBubble; }
        void setCancelBubble(bool cancel) { m_cancelBubble = cancel; }

        Event* underlyingEvent() const { return m_underlyingEvent.get(); }
        void setUnderlyingEvent(PassRefPtr<Event>);

        virtual bool storesResultAsString() const;
        virtual void storeResult(const String&);

        virtual Clipboard* clipboard() const { return 0; }


    protected:
        Event();
        Event(const AtomicString& type, bool canBubble, bool cancelable);

        virtual void receivedTarget();
        bool dispatched() const { return m_target; }

    private:
        AtomicString m_type;
        bool m_canBubble;
        bool m_cancelable;

        bool m_propagationStopped;
        bool m_immediatePropagationStopped;
        bool m_defaultPrevented;
        bool m_defaultHandled;
        bool m_cancelBubble;

        unsigned short m_eventPhase;
        EventTarget* m_currentTarget;
        RefPtr<EventTarget> m_target;
        DOMTimeStamp m_createTime;

        RefPtr<Event> m_underlyingEvent;
    };

class EventDispatchMediator {
public:
    explicit EventDispatchMediator(PassRefPtr<Event>);
    virtual ~EventDispatchMediator();

    virtual bool dispatchEvent(EventDispatcher*) const;

protected:
    EventDispatchMediator();

    Event* event() const;
    void setEvent(PassRefPtr<Event>);

private:
    RefPtr<Event> m_event;
};

inline EventDispatchMediator::EventDispatchMediator()
{
}

inline Event* EventDispatchMediator::event() const
{
    return m_event.get();
}

inline void EventDispatchMediator::setEvent(PassRefPtr<Event> event)
{
    m_event = event;
}

} // namespace WebCore

#endif // Event_h
