/*
 * Copyright (C) 2010, 2013 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. 
 */

#ifndef FullscreenVideoController_h
#define FullscreenVideoController_h

#if ENABLE(VIDEO)

#include <WebCore/HTMLVideoElement.h>
#include <WebCore/Image.h>
#include <WebCore/IntPoint.h>
#include <WebCore/IntSize.h>
#include <WebCore/MediaPlayerPrivateFullscreenWindow.h>
#include <wtf/RefPtr.h>
#include <wtf/win/GDIObject.h>

namespace WebCore {
class GraphicsContext;
class PlatformCALayer;
}

class HUDWidget {
public:
    HUDWidget(const WebCore::IntRect& rect) : m_rect(rect) { }
    
    virtual ~HUDWidget() { }

    virtual void draw(WebCore::GraphicsContext&) = 0;
    virtual void drag(const WebCore::IntPoint&, bool start) = 0;
    bool hitTest(const WebCore::IntPoint& point) const { return m_rect.contains(point); }

protected:
    WebCore::IntRect m_rect;
};

class HUDButton : public HUDWidget {
public:
    enum HUDButtonType {
        NoButton,
        PlayPauseButton,
        TimeSliderButton,
        VolumeUpButton,
        VolumeSliderButton,
        VolumeDownButton,
        ExitFullscreenButton
    };

    HUDButton(HUDButtonType, const WebCore::IntPoint&);
    ~HUDButton() { }

    virtual void draw(WebCore::GraphicsContext&);
    virtual void drag(const WebCore::IntPoint&, bool start) { }
    void setShowAltButton(bool b)  { m_showAltButton = b; }

private:
    RefPtr<WebCore::Image> m_buttonImage;
    RefPtr<WebCore::Image> m_buttonImageAlt;
    HUDButtonType m_type;
    bool m_showAltButton;
};

class HUDSlider : public HUDWidget {
public:
    enum HUDSliderButtonShape { RoundButton, DiamondButton };

    HUDSlider(HUDSliderButtonShape, int buttonSize, const WebCore::IntRect& rect);
    ~HUDSlider() { }

    virtual void draw(WebCore::GraphicsContext&);
    virtual void drag(const WebCore::IntPoint&, bool start);
    float value() const { return static_cast<float>(m_buttonPosition) / (m_rect.width() - m_buttonSize); }
    void setValue(float value) { m_buttonPosition = static_cast<int>(value * (m_rect.width() - m_buttonSize)); }

private:
    HUDSliderButtonShape m_buttonShape;
    int m_buttonSize;
    int m_buttonPosition;
    int m_dragStartOffset;
};

class FullscreenVideoController : WebCore::MediaPlayerPrivateFullscreenClient {
    WTF_MAKE_NONCOPYABLE(FullscreenVideoController);
public:
    FullscreenVideoController();
    virtual ~FullscreenVideoController();

    void setVideoElement(WebCore::HTMLVideoElement*);
    WebCore::HTMLVideoElement* videoElement() const { return m_videoElement.get(); }

    void enterFullscreen();
    void exitFullscreen();

private:
    // MediaPlayerPrivateFullscreenWindowClient
    virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM);
    
    void ensureWindow();
    
    bool canPlay() const;
    void play();
    void pause();
    float volume() const;
    void setVolume(float);
    float currentTime() const;
    void setCurrentTime(float);
    float duration() const;
    void beginScrubbing();
    void endScrubbing();

    WebCore::IntPoint fullscreenToHUDCoordinates(const WebCore::IntPoint& point) const
    {
        return WebCore::IntPoint(point.x()- m_hudPosition.x(), point.y() - m_hudPosition.y());
    }

    static void registerHUDWindowClass();
    static LRESULT CALLBACK hudWndProc(HWND, UINT message, WPARAM, LPARAM);
    void createHUDWindow();
    void timerFired();

    void togglePlay();
    void draw();

    void onChar(int c);
    void onMouseDown(const WebCore::IntPoint&);
    void onMouseMove(const WebCore::IntPoint&);
    void onMouseUp(const WebCore::IntPoint&);
    void onKeyDown(int virtualKey);

    RefPtr<WebCore::HTMLVideoElement> m_videoElement;

    HWND m_hudWindow;
    GDIObject<HBITMAP> m_bitmap;
    WebCore::IntSize m_fullscreenSize;
    WebCore::IntPoint m_hudPosition;
    std::unique_ptr<WebCore::MediaPlayerPrivateFullscreenWindow> m_fullscreenWindow;

#if USE(CA)
    class LayerClient;
    friend class LayerClient;
    std::unique_ptr<LayerClient> m_layerClient;
    RefPtr<WebCore::PlatformCALayer> m_rootChild;
#endif

    HUDButton m_playPauseButton;
    HUDButton m_timeSliderButton;
    HUDButton m_volumeUpButton;
    HUDButton m_volumeSliderButton;
    HUDButton m_volumeDownButton;
    HUDButton m_exitFullscreenButton;
    HUDSlider m_volumeSlider;
    HUDSlider m_timeSlider;

    HUDWidget* m_hitWidget;
    WebCore::IntPoint m_moveOffset;
    bool m_movingWindow;
    WebCore::Timer m_timer;
};

#endif

#endif // FullscreenVideoController_h
