/*
 * Copyright (C) 2004, 2006, 2008 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 COMPUTER, 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 COMPUTER, 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"
#include "platform/scroll/Scrollbar.h"

#include <algorithm>
#include "platform/graphics/GraphicsContext.h"
#include "platform/PlatformGestureEvent.h"
#include "platform/PlatformMouseEvent.h"
#include "platform/FrameWidget.h"
#include "platform/scroll/ScrollableArea.h"
#include "platform/scroll/ScrollAnimator.h"
#include "platform/scroll/Scrollbar.h"
#include "public/platform/Platform.h"
#include "public/platform/WebPoint.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebScrollbarBehavior.h"
#include "public/platform/WebThemeEngine.h"

#if ((OS(POSIX) && !OS(MACOSX)) || OS(WIN))
// The position of the scrollbar thumb affects the appearance of the steppers, so
// when the thumb moves, we have to invalidate them for painting.
#define THUMB_POSITION_AFFECTS_BUTTONS
#endif

namespace blink {

static const int kThumbThickness = 3;
static const int kScrollbarMargin = 3;

PassRefPtr<Scrollbar> Scrollbar::create(ScrollableArea* scrollableArea, ScrollbarOrientation orientation)
{
    return adoptRef(new Scrollbar(scrollableArea, orientation));
}

Scrollbar::Scrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation)
    : m_scrollableArea(scrollableArea)
    , m_orientation(orientation)
    , m_visibleSize(0)
    , m_totalSize(0)
    , m_currentPos(0)
    , m_dragOrigin(0)
    , m_hoveredPart(NoPart)
    , m_pressedPart(NoPart)
    , m_pressedPos(0)
    , m_scrollPos(0)
    , m_documentDragPos(0)
    , m_enabled(true)
    , m_scrollTimer(this, &Scrollbar::autoscrollTimerFired)
    , m_overlapsResizer(false)
    , m_suppressInvalidation(false)
    , m_isAlphaLocked(false)
{
    // FIXME: This is ugly and would not be necessary if we fix cross-platform code to actually query for
    // scrollbar thickness and use it when sizing scrollbars (rather than leaving one dimension of the scrollbar
    // alone when sizing).
    int thickness = scrollbarThickness();
    Widget::setFrameRect(IntRect(0, 0, thickness, thickness));

    m_currentPos = scrollableAreaCurrentPos();
}

Scrollbar::~Scrollbar()
{
    stopTimerIfNeeded();
}

void Scrollbar::removeFromParent()
{
    if (parent())
        toFrameWidget(parent())->removeChild(this);
}

ScrollbarOverlayStyle Scrollbar::scrollbarOverlayStyle() const
{
    return m_scrollableArea ? m_scrollableArea->scrollbarOverlayStyle() : ScrollbarOverlayStyleDefault;
}

void Scrollbar::getTickmarks(Vector<IntRect>& tickmarks) const
{
    if (m_scrollableArea)
        m_scrollableArea->getTickmarks(tickmarks);
}

bool Scrollbar::isScrollableAreaActive() const
{
    return m_scrollableArea && m_scrollableArea->isActive();
}

bool Scrollbar::isScrollViewScrollbar() const
{
    // FIXME(sky): Remove
    return false;
}

bool Scrollbar::isLeftSideVerticalScrollbar() const
{
    if (m_orientation == VerticalScrollbar && m_scrollableArea)
        return m_scrollableArea->shouldPlaceVerticalScrollbarOnLeft();
    return false;
}

void Scrollbar::offsetDidChange()
{
    ASSERT(m_scrollableArea);

    float position = scrollableAreaCurrentPos();
    if (position == m_currentPos)
        return;

    int oldThumbPosition = theme()->thumbPosition();
    m_currentPos = position;
    updateThumbPosition();
    if (m_pressedPart == ThumbPart)
        setPressedPos(m_pressedPos + theme()->thumbPosition() - oldThumbPosition);
}

void Scrollbar::setProportion(int visibleSize, int totalSize)
{
    if (visibleSize == m_visibleSize && totalSize == m_totalSize)
        return;

    m_visibleSize = visibleSize;
    m_totalSize = totalSize;

    updateThumbProportion();
}

void Scrollbar::updateThumb()
{
#ifdef THUMB_POSITION_AFFECTS_BUTTONS
    invalidate();
#else
    theme()->invalidateParts();
#endif
}

void Scrollbar::updateThumbPosition()
{
    updateThumb();
}

void Scrollbar::updateThumbProportion()
{
    updateThumb();
}

void Scrollbar::paint(GraphicsContext* context, const IntRect& damageRect)
{
    if (!frameRect().intersects(damageRect))
        return;

    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    splitTrack(trackRect(), startTrackRect, thumbRect, endTrackRect);
    if (damageRect.intersects(thumbRect))
        paintThumb(context, thumbRect);
}

void Scrollbar::autoscrollTimerFired(Timer<Scrollbar>*)
{
    autoscrollPressedPart(theme()->autoscrollTimerDelay());
}

static bool thumbUnderMouse(Scrollbar* scrollbar)
{
    int thumbPos = scrollbar->theme()->trackPosition() + scrollbar->theme()->thumbPosition();
    int thumbLength = scrollbar->theme()->thumbLength();
    return scrollbar->pressedPos() >= thumbPos && scrollbar->pressedPos() < thumbPos + thumbLength;
}

void Scrollbar::autoscrollPressedPart(double delay)
{
    // Don't do anything for the thumb or if nothing was pressed.
    if (m_pressedPart == ThumbPart || m_pressedPart == NoPart)
        return;

    // Handle the track.
    if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && thumbUnderMouse(this)) {
        theme()->invalidatePart(m_pressedPart);
        setHoveredPart(ThumbPart);
        return;
    }

    // Handle the arrows and track.
    if (m_scrollableArea && m_scrollableArea->scroll(pressedPartScrollDirection(), pressedPartScrollGranularity()))
        startTimerIfNeeded(delay);
}

void Scrollbar::startTimerIfNeeded(double delay)
{
    // Don't do anything for the thumb.
    if (m_pressedPart == ThumbPart)
        return;

    // Handle the track.  We halt track scrolling once the thumb is level
    // with us.
    if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && thumbUnderMouse(this)) {
        theme()->invalidatePart(m_pressedPart);
        setHoveredPart(ThumbPart);
        return;
    }

    // We can't scroll if we've hit the beginning or end.
    ScrollDirection dir = pressedPartScrollDirection();
    if (dir == ScrollUp || dir == ScrollLeft) {
        if (m_currentPos == 0)
            return;
    } else {
        if (m_currentPos == maximum())
            return;
    }

    m_scrollTimer.startOneShot(delay, FROM_HERE);
}

void Scrollbar::stopTimerIfNeeded()
{
    if (m_scrollTimer.isActive())
        m_scrollTimer.stop();
}

ScrollDirection Scrollbar::pressedPartScrollDirection()
{
    if (m_orientation == HorizontalScrollbar) {
        if (m_pressedPart == BackTrackPart)
            return ScrollLeft;
        return ScrollRight;
    } else {
        if (m_pressedPart == BackTrackPart)
            return ScrollUp;
        return ScrollDown;
    }
}

ScrollGranularity Scrollbar::pressedPartScrollGranularity()
{
    // FIXME(sky): Remove
    return ScrollByPage;
}

void Scrollbar::moveThumb(int pos)
{
    if (!m_scrollableArea)
        return;

    int delta = pos - m_pressedPos;

    // Drag the thumb.
    int thumbPos = theme()->thumbPosition();
    int thumbLen = theme()->thumbLength();
    int trackLen = theme()->trackLength();
    if (delta > 0)
        delta = std::min(trackLen - thumbLen - thumbPos, delta);
    else if (delta < 0)
        delta = std::max(-thumbPos, delta);

    float minPos = m_scrollableArea->minimumScrollPosition(m_orientation);
    float maxPos = m_scrollableArea->maximumScrollPosition(m_orientation);
    if (delta) {
        float newPosition = static_cast<float>(thumbPos + delta) * (maxPos - minPos) / (trackLen - thumbLen) + minPos;
        m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, newPosition);
    }
}

void Scrollbar::setHoveredPart(ScrollbarPart part)
{
    if (part == m_hoveredPart)
        return;

    if (m_pressedPart == NoPart) {  // When there's a pressed part, we don't draw a hovered state, so there's no reason to invalidate.
        theme()->invalidatePart(part);
        theme()->invalidatePart(m_hoveredPart);
    }
    m_hoveredPart = part;
}

void Scrollbar::setPressedPart(ScrollbarPart part)
{
    if (m_pressedPart != NoPart)
        theme()->invalidatePart(m_pressedPart);
    m_pressedPart = part;
    if (m_pressedPart != NoPart)
        theme()->invalidatePart(m_pressedPart);
    else if (m_hoveredPart != NoPart)  // When we no longer have a pressed part, we can start drawing a hovered state on the hovered part.
        theme()->invalidatePart(m_hoveredPart);
}

bool Scrollbar::gestureEvent(const PlatformGestureEvent& evt)
{
    switch (evt.type()) {
    case PlatformEvent::GestureTapDown:
        // FIXME(sky): Is setting the pressed part needed since we only have overlay scrollbars?
        setPressedPart(NoPart);
        m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();
        return true;
    case PlatformEvent::GestureTapDownCancel:
    case PlatformEvent::GestureScrollBegin:
        if (m_pressedPart != ThumbPart)
            return false;
        m_scrollPos = m_pressedPos;
        return true;
    case PlatformEvent::GestureScrollUpdate:
    case PlatformEvent::GestureScrollUpdateWithoutPropagation:
        if (m_pressedPart != ThumbPart)
            return false;
        m_scrollPos += orientation() == HorizontalScrollbar ? evt.deltaX() : evt.deltaY();
        moveThumb(m_scrollPos);
        return true;
    case PlatformEvent::GestureScrollEnd:
    case PlatformEvent::GestureLongPress:
    case PlatformEvent::GestureFlingStart:
        m_scrollPos = 0;
        m_pressedPos = 0;
        setPressedPart(NoPart);
        return false;
    case PlatformEvent::GestureTap: {
        if (m_pressedPart != ThumbPart && m_pressedPart != NoPart && m_scrollableArea
            && m_scrollableArea->scroll(pressedPartScrollDirection(), pressedPartScrollGranularity())) {
            return true;
        }
        m_scrollPos = 0;
        m_pressedPos = 0;
        setPressedPart(NoPart);
        return false;
    }
    default:
        // By default, we assume that gestures don't deselect the scrollbar.
        return true;
    }
}

void Scrollbar::mouseMoved(const PlatformMouseEvent& evt)
{
    if (m_pressedPart == ThumbPart) {
        if (theme()->shouldSnapBackToDragOrigin(evt)) {
            if (m_scrollableArea)
                m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, m_dragOrigin + m_scrollableArea->minimumScrollPosition(m_orientation));
        } else {
            moveThumb(m_orientation == HorizontalScrollbar ?
                      convertFromContainingWindow(evt.position()).x() :
                      convertFromContainingWindow(evt.position()).y());
        }
        return;
    }

    if (m_pressedPart != NoPart)
        m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();

    // FIXME(sky): Cleanup this code now that part is always NoPart.
    ScrollbarPart part = NoPart;
    if (part != m_hoveredPart) {
        if (m_pressedPart != NoPart) {
            if (part == m_pressedPart) {
                // The mouse is moving back over the pressed part.  We
                // need to start up the timer action again.
                startTimerIfNeeded(theme()->autoscrollTimerDelay());
                theme()->invalidatePart(m_pressedPart);
            } else if (m_hoveredPart == m_pressedPart) {
                // The mouse is leaving the pressed part.  Kill our timer
                // if needed.
                stopTimerIfNeeded();
                theme()->invalidatePart(m_pressedPart);
            }
        }

        setHoveredPart(part);
    }

    return;
}

void Scrollbar::mouseEntered()
{
    if (m_scrollableArea)
        m_scrollableArea->mouseEnteredScrollbar(this);
}

void Scrollbar::mouseExited()
{
    if (m_scrollableArea)
        m_scrollableArea->mouseExitedScrollbar(this);
    setHoveredPart(NoPart);
}

void Scrollbar::mouseUp(const PlatformMouseEvent& mouseEvent)
{
    setPressedPart(NoPart);
    m_pressedPos = 0;
    stopTimerIfNeeded();

    if (m_scrollableArea) {
        // m_hoveredPart won't be updated until the next mouseMoved or mouseDown, so we have to hit test
        // to really know if the mouse has exited the scrollbar on a mouseUp.
        m_scrollableArea->mouseExitedScrollbar(this);
    }
}

void Scrollbar::mouseDown(const PlatformMouseEvent& evt)
{
    // Early exit for right click
    if (evt.button() == RightButton)
        return;

    // FIXME(sky): Do we still need setPressedPart now that we only set it to NoPart?
    setPressedPart(NoPart);
    int pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y();

    if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme()->shouldCenterOnThumb(evt)) {
        setHoveredPart(ThumbPart);
        setPressedPart(ThumbPart);
        m_dragOrigin = m_currentPos;
        int thumbLen = theme()->thumbLength();
        int desiredPos = pressedPos;
        // Set the pressed position to the middle of the thumb so that when we do the move, the delta
        // will be from the current pixel position of the thumb to the new desired position for the thumb.
        m_pressedPos = theme()->trackPosition() + theme()->thumbPosition() + thumbLen / 2;
        moveThumb(desiredPos);
        return;
    } else if (m_pressedPart == ThumbPart)
        m_dragOrigin = m_currentPos;

    m_pressedPos = pressedPos;

    autoscrollPressedPart(theme()->initialAutoscrollTimerDelay());
}

void Scrollbar::setEnabled(bool e)
{
    if (m_enabled == e)
        return;
    m_enabled = e;
    invalidate();
}

bool Scrollbar::isOverlayScrollbar() const
{
    // FIXME(sky): Remove
    return true;
}

bool Scrollbar::shouldParticipateInHitTesting()
{
    // Non-overlay scrollbars should always participate in hit testing.
    if (!isOverlayScrollbar())
        return true;
    return m_scrollableArea->scrollAnimator()->shouldScrollbarParticipateInHitTesting(this);
}

bool Scrollbar::isWindowActive() const
{
    return m_scrollableArea && m_scrollableArea->isActive();
}

void Scrollbar::invalidateRect(const IntRect& rect)
{
    if (suppressInvalidation())
        return;

    if (m_scrollableArea)
        m_scrollableArea->invalidateScrollbar(this, rect);
}

IntRect Scrollbar::convertToContainingView(const IntRect& localRect) const
{
    if (m_scrollableArea)
        return m_scrollableArea->convertFromScrollbarToContainingView(this, localRect);

    return Widget::convertToContainingView(localRect);
}

IntRect Scrollbar::convertFromContainingView(const IntRect& parentRect) const
{
    if (m_scrollableArea)
        return m_scrollableArea->convertFromContainingViewToScrollbar(this, parentRect);

    return Widget::convertFromContainingView(parentRect);
}

IntPoint Scrollbar::convertToContainingView(const IntPoint& localPoint) const
{
    if (m_scrollableArea)
        return m_scrollableArea->convertFromScrollbarToContainingView(this, localPoint);

    return Widget::convertToContainingView(localPoint);
}

IntPoint Scrollbar::convertFromContainingView(const IntPoint& parentPoint) const
{
    if (m_scrollableArea)
        return m_scrollableArea->convertFromContainingViewToScrollbar(this, parentPoint);

    return Widget::convertFromContainingView(parentPoint);
}

float Scrollbar::scrollableAreaCurrentPos() const
{
    if (!m_scrollableArea)
        return 0;

    if (m_orientation == HorizontalScrollbar)
        return m_scrollableArea->scrollPosition().x() - m_scrollableArea->minimumScrollPosition().x();

    return m_scrollableArea->scrollPosition().y() - m_scrollableArea->minimumScrollPosition().y();
}

int Scrollbar::scrollbarThickness()
{
    return kThumbThickness + kScrollbarMargin;
}

void Scrollbar::invalidatePart(ScrollbarPart part)
{
    if (part == NoPart)
        return;

    IntRect result;

    IntRect beforeThumbRect, thumbRect, afterThumbRect;
    splitTrack(trackRect(), beforeThumbRect, thumbRect, afterThumbRect);
    if (part == BackTrackPart)
        result = beforeThumbRect;
    else if (part == ForwardTrackPart)
        result = afterThumbRect;
    else
        result = thumbRect;

    result.moveBy(-location());
    invalidateRect(result);
}

void Scrollbar::paintScrollCorner(GraphicsContext* context, const IntRect& cornerRect)
{
    if (cornerRect.isEmpty())
        return;
    blink::Platform::current()->themeEngine()->paint(context->canvas(), blink::WebThemeEngine::PartScrollbarCorner, blink::WebThemeEngine::StateNormal, blink::WebRect(cornerRect), 0);
}

void Scrollbar::paintOverhangBackground(GraphicsContext* context, const IntRect& horizontalOverhangRect, const IntRect& verticalOverhangRect, const IntRect& dirtyRect)
{
    context->setFillColor(Color::white);
    if (!horizontalOverhangRect.isEmpty())
        context->fillRect(intersection(horizontalOverhangRect, dirtyRect));
    if (!verticalOverhangRect.isEmpty())
        context->fillRect(intersection(verticalOverhangRect, dirtyRect));
}

bool Scrollbar::shouldCenterOnThumb(const PlatformMouseEvent& evt)
{
    return blink::Platform::current()->scrollbarBehavior()->shouldCenterOnThumb(static_cast<blink::WebScrollbarBehavior::Button>(evt.button()), evt.shiftKey(), evt.altKey());
}

bool Scrollbar::shouldSnapBackToDragOrigin(const PlatformMouseEvent& evt)
{
    IntPoint mousePosition = convertFromContainingWindow(evt.position());
    mousePosition.move(x(), y());
    return blink::Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin(mousePosition, trackRect(), orientation() == HorizontalScrollbar);
}

int Scrollbar::thumbPosition()
{
    if (!totalSize())
        return 0;

    int trackLen = trackLength();
    float proportion = static_cast<float>(currentPos()) / totalSize();
    return round(proportion * trackLen);
}

int Scrollbar::thumbLength()
{
    int trackLen = trackLength();

    if (!totalSize())
        return trackLen;

    float proportion = static_cast<float>(visibleSize()) / totalSize();
    int length = round(proportion * trackLen);
    length = std::min(std::max(length, minimumThumbLength()), trackLen);
    return length;
}

int Scrollbar::trackPosition()
{
    IntRect rect = trackRect();
    return (orientation() == HorizontalScrollbar) ? rect.x() - x() : rect.y() - y();
}

int Scrollbar::trackLength()
{
    IntRect rect = trackRect();
    return (orientation() == HorizontalScrollbar) ? rect.width() : rect.height();
}

IntRect Scrollbar::trackRect()
{
    IntRect rect = frameRect();
    if (orientation() == HorizontalScrollbar)
        rect.inflateX(-kScrollbarMargin);
    else
        rect.inflateY(-kScrollbarMargin);
    return rect;
}

IntRect Scrollbar::thumbRect()
{
    IntRect track = trackRect();
    IntRect startTrackRect;
    IntRect thumbRect;
    IntRect endTrackRect;
    splitTrack(track, startTrackRect, thumbRect, endTrackRect);

    return thumbRect;
}

int Scrollbar::thumbThickness()
{
    return kThumbThickness;
}

int Scrollbar::minimumThumbLength()
{
    return scrollbarThickness();
}

void Scrollbar::splitTrack(const IntRect& trackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect)
{
    // This function won't even get called unless we're big enough to have some combination of these three rects where at least
    // one of them is non-empty.
    int thumbPos = thumbPosition();
    if (orientation() == HorizontalScrollbar) {
        thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength(), height());
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumbRect.width() / 2, trackRect.height());
        afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height());
    } else {
        thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, width(), thumbLength());
        beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos + thumbRect.height() / 2);
        afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY());
    }
}

void Scrollbar::paintThumb(GraphicsContext* context, const IntRect& rect)
{
    // FIXME(sky): This function appears to be dead code.
    IntRect thumbRect = rect;
    if (orientation() == HorizontalScrollbar) {
        thumbRect.setHeight(thumbRect.height() - kScrollbarMargin);
    } else {
        thumbRect.setWidth(thumbRect.width() - kScrollbarMargin);
        if (isLeftSideVerticalScrollbar())
            thumbRect.setX(thumbRect.x() + kScrollbarMargin);
    }

    DEFINE_STATIC_LOCAL(Color, color, (128, 128, 128, 128));
    context->fillRect(thumbRect, color);
}

} // namespace blink
