/*
 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
 * Copyright (C) 2011, 2012 Google 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.
 */

#include "config.h"

#if ENABLE(VIDEO)
#include "MediaControls.h"

#include "EventNames.h"
#include "MouseEvent.h"
#include "Page.h"
#include "RenderElement.h"
#include "RenderTheme.h"
#include "Settings.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(MediaControls);

MediaControls::MediaControls(Document& document)
    : HTMLDivElement(HTMLNames::divTag, document)
    , m_mediaController(0)
    , m_panel(0)
#if ENABLE(VIDEO_TRACK)
    , m_textDisplayContainer(0)
#endif
    , m_playButton(0)
    , m_currentTimeDisplay(0)
    , m_timeline(0)
    , m_panelMuteButton(0)
    , m_volumeSlider(0)
    , m_toggleClosedCaptionsButton(0)
    , m_fullScreenButton(0)
    , m_hideFullscreenControlsTimer(*this, &MediaControls::hideFullscreenControlsTimerFired)
    , m_isFullscreen(false)
    , m_isMouseOverControls(false)
{
    setPseudo(AtomicString("-webkit-media-controls", AtomicString::ConstructFromLiteral));
}

void MediaControls::setMediaController(MediaControllerInterface* controller)
{
    if (m_mediaController == controller)
        return;
    m_mediaController = controller;

    if (m_panel)
        m_panel->setMediaController(controller);
#if ENABLE(VIDEO_TRACK)
    if (m_textDisplayContainer)
        m_textDisplayContainer->setMediaController(controller);
#endif
    if (m_playButton)
        m_playButton->setMediaController(controller);
    if (m_currentTimeDisplay)
        m_currentTimeDisplay->setMediaController(controller);
    if (m_timeline)
        m_timeline->setMediaController(controller);
    if (m_panelMuteButton)
        m_panelMuteButton->setMediaController(controller);
    if (m_volumeSlider)
        m_volumeSlider->setMediaController(controller);
    if (m_toggleClosedCaptionsButton)
        m_toggleClosedCaptionsButton->setMediaController(controller);
    if (m_fullScreenButton)
        m_fullScreenButton->setMediaController(controller);
}

void MediaControls::reset()
{
    m_playButton->updateDisplayType();

    updateCurrentTimeDisplay();

    double duration = m_mediaController->duration();
    if (std::isfinite(duration) || RenderTheme::singleton().hasOwnDisabledStateHandlingFor(MediaSliderPart)) {
        m_timeline->setDuration(duration);
        m_timeline->setPosition(m_mediaController->currentTime());
    }

    if (m_mediaController->hasAudio() || RenderTheme::singleton().hasOwnDisabledStateHandlingFor(MediaMuteButtonPart))
        m_panelMuteButton->show();
    else
        m_panelMuteButton->hide();

    if (m_volumeSlider) {
        if (!m_mediaController->hasAudio())
            m_volumeSlider->hide();
        else {
            m_volumeSlider->show();
            setSliderVolume();
        }
    }

    refreshClosedCaptionsButtonVisibility();

    if (m_fullScreenButton) {
        if (m_mediaController->supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenModeStandard) && m_mediaController->hasVideo())
            m_fullScreenButton->show();
        else
            m_fullScreenButton->hide();
    }

    makeOpaque();
}

void MediaControls::reportedError()
{
    auto& theme = RenderTheme::singleton();
    if (!theme.hasOwnDisabledStateHandlingFor(MediaMuteButtonPart)) {
        m_panelMuteButton->hide();
        m_volumeSlider->hide();
    }

    if (m_toggleClosedCaptionsButton && !theme.hasOwnDisabledStateHandlingFor(MediaToggleClosedCaptionsButtonPart))
        m_toggleClosedCaptionsButton->hide();

    if (m_fullScreenButton && !theme.hasOwnDisabledStateHandlingFor(MediaEnterFullscreenButtonPart))
        m_fullScreenButton->hide();
}

void MediaControls::loadedMetadata()
{
    reset();
}

void MediaControls::show()
{
    makeOpaque();
    m_panel->setIsDisplayed(true);
    m_panel->show();
}

void MediaControls::hide()
{
    m_panel->setIsDisplayed(false);
    m_panel->hide();
}

void MediaControls::makeOpaque()
{
    m_panel->makeOpaque();
}

void MediaControls::makeTransparent()
{
    m_panel->makeTransparent();
}

bool MediaControls::shouldHideControls()
{
    return !m_panel->hovered();
}

void MediaControls::bufferingProgressed()
{
    // We only need to update buffering progress when paused, during normal
    // playback playbackProgressed() will take care of it.
    if (m_mediaController->paused())
        m_timeline->setPosition(m_mediaController->currentTime());
}

void MediaControls::playbackStarted()
{
    m_playButton->updateDisplayType();
    m_timeline->setPosition(m_mediaController->currentTime());
    updateCurrentTimeDisplay();

    if (m_isFullscreen)
        startHideFullscreenControlsTimer();
}

void MediaControls::playbackProgressed()
{
    m_timeline->setPosition(m_mediaController->currentTime());
    updateCurrentTimeDisplay();

    if (!m_isMouseOverControls && m_mediaController->hasVideo())
        makeTransparent();
}

void MediaControls::playbackStopped()
{
    m_playButton->updateDisplayType();
    m_timeline->setPosition(m_mediaController->currentTime());
    updateCurrentTimeDisplay();
    makeOpaque();

    stopHideFullscreenControlsTimer();
}

void MediaControls::updateCurrentTimeDisplay()
{
    double now = m_mediaController->currentTime();
    m_currentTimeDisplay->setInnerText(RenderTheme::singleton().formatMediaControlsTime(now));
    m_currentTimeDisplay->setCurrentValue(now);
}

void MediaControls::showVolumeSlider()
{
    if (!m_mediaController->hasAudio())
        return;

    m_volumeSlider->show();
}

void MediaControls::changedMute()
{
    m_panelMuteButton->changedMute();
}

void MediaControls::changedVolume()
{
    if (m_volumeSlider)
        setSliderVolume();
    if (m_panelMuteButton && m_panelMuteButton->renderer())
        m_panelMuteButton->renderer()->repaint();
}

void MediaControls::changedClosedCaptionsVisibility()
{
    if (m_toggleClosedCaptionsButton)
        m_toggleClosedCaptionsButton->updateDisplayType();
}

void MediaControls::refreshClosedCaptionsButtonVisibility()
{
    if (!m_toggleClosedCaptionsButton)
        return;

    if (m_mediaController->hasClosedCaptions())
        m_toggleClosedCaptionsButton->show();
    else
        m_toggleClosedCaptionsButton->hide();
}

void MediaControls::closedCaptionTracksChanged()
{
    refreshClosedCaptionsButtonVisibility();
}

void MediaControls::enteredFullscreen()
{
    m_isFullscreen = true;
    m_fullScreenButton->setIsFullscreen(true);

    if (Page* page = document().page())
        page->chrome().setCursorHiddenUntilMouseMoves(true);

    startHideFullscreenControlsTimer();
#if ENABLE(VIDEO_TRACK)
    if (m_textDisplayContainer)
        m_textDisplayContainer->enteredFullscreen();
#endif
}

void MediaControls::exitedFullscreen()
{
    m_isFullscreen = false;
    m_fullScreenButton->setIsFullscreen(false);
    stopHideFullscreenControlsTimer();
#if ENABLE(VIDEO_TRACK)
    if (m_textDisplayContainer)
        m_textDisplayContainer->exitedFullscreen();
#endif
}

void MediaControls::defaultEventHandler(Event& event)
{
    HTMLDivElement::defaultEventHandler(event);

    if (event.type() == eventNames().mouseoverEvent) {
        if (!containsRelatedTarget(event)) {
            m_isMouseOverControls = true;
            if (!m_mediaController->canPlay()) {
                makeOpaque();
                if (shouldHideControls())
                    startHideFullscreenControlsTimer();
            }
        }
        return;
    }

    if (event.type() == eventNames().mouseoutEvent) {
        if (!containsRelatedTarget(event)) {
            m_isMouseOverControls = false;
            stopHideFullscreenControlsTimer();
        }
        return;
    }

    if (event.type() == eventNames().mousemoveEvent) {
        if (m_isFullscreen) {
            // When we get a mouse move in fullscreen mode, show the media controls, and start a timer
            // that will hide the media controls after a 3 seconds without a mouse move.
            makeOpaque();
            if (shouldHideControls())
                startHideFullscreenControlsTimer();
        }
        return;
    }
}

void MediaControls::hideFullscreenControlsTimerFired()
{
    if (m_mediaController->paused())
        return;

    if (!m_isFullscreen)
        return;

    if (!shouldHideControls())
        return;

    if (Page* page = document().page())
        page->chrome().setCursorHiddenUntilMouseMoves(true);

    makeTransparent();
}

void MediaControls::startHideFullscreenControlsTimer()
{
    if (!m_isFullscreen)
        return;

    Page* page = document().page();
    if (!page)
        return;

    m_hideFullscreenControlsTimer.startOneShot(page->settings().timeWithoutMouseMovementBeforeHidingControls());
}

void MediaControls::stopHideFullscreenControlsTimer()
{
    m_hideFullscreenControlsTimer.stop();
}

bool MediaControls::containsRelatedTarget(Event& event)
{
    if (!is<MouseEvent>(event))
        return false;
    auto relatedTarget = downcast<MouseEvent>(event).relatedTarget();
    return is<Node>(relatedTarget) && contains(&downcast<Node>(*relatedTarget));
}

#if ENABLE(VIDEO_TRACK)

void MediaControls::createTextTrackDisplay()
{
    if (m_textDisplayContainer)
        return;

    auto textDisplayContainer = MediaControlTextTrackContainerElement::create(document());
    m_textDisplayContainer = textDisplayContainer.ptr();

    if (m_mediaController)
        m_textDisplayContainer->setMediaController(m_mediaController);

    // Insert it before the first controller element so it always displays behind the controls.
    insertBefore(textDisplayContainer, m_panel);
}

void MediaControls::showTextTrackDisplay()
{
    if (!m_textDisplayContainer)
        createTextTrackDisplay();
    m_textDisplayContainer->show();
}

void MediaControls::hideTextTrackDisplay()
{
    if (!m_textDisplayContainer)
        createTextTrackDisplay();
    m_textDisplayContainer->hide();
}

void MediaControls::updateTextTrackDisplay()
{
    if (!m_textDisplayContainer)
        createTextTrackDisplay();

    m_textDisplayContainer->updateDisplay();
}
    
void MediaControls::textTrackPreferencesChanged()
{
    closedCaptionTracksChanged();
    if (m_textDisplayContainer)
        m_textDisplayContainer->updateSizes(true);
}

void MediaControls::clearTextDisplayContainer()
{
    if (m_textDisplayContainer)
        m_textDisplayContainer->removeChildren();
}

#endif

void MediaControls::setSliderVolume()
{
    m_volumeSlider->setVolume(m_mediaController->muted() ? 0.0 : m_mediaController->volume());
}

}

#endif
