/*
 * Copyright (C) 2011-2014 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. AND ITS CONTRIBUTORS ``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 ITS 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 "TileCoverageMap.h"

#include "GraphicsContext.h"
#include "TileController.h"
#include "TileGrid.h"

namespace WebCore {

TileCoverageMap::TileCoverageMap(const TileController& controller)
    : m_controller(controller)
    , m_updateTimer(*this, &TileCoverageMap::updateTimerFired)
    , m_layer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeSimpleLayer, this))
    , m_visibleViewportIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    , m_layoutViewportIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    , m_coverageRectIndicatorLayer(controller.rootLayer().createCompatibleLayer(PlatformCALayer::LayerTypeLayer, nullptr))
    , m_position(FloatPoint(0, controller.topContentInset()))
{
    m_layer.get().setOpacity(0.75);
    m_layer.get().setAnchorPoint(FloatPoint3D());
    m_layer.get().setBorderColor(Color::black);
    m_layer.get().setBorderWidth(1);
    m_layer.get().setPosition(FloatPoint(2, 2));
    m_layer.get().setContentsScale(m_controller.deviceScaleFactor());

    m_visibleViewportIndicatorLayer.get().setName("visible viewport indicator");
    m_visibleViewportIndicatorLayer.get().setBorderWidth(2);
    m_visibleViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
    m_visibleViewportIndicatorLayer.get().setBorderColor(Color(255, 0, 0, 200));

    m_layoutViewportIndicatorLayer.get().setName("layout viewport indicator");
    m_layoutViewportIndicatorLayer.get().setBorderWidth(2);
    m_layoutViewportIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
    m_layoutViewportIndicatorLayer.get().setBorderColor(Color(0, 128, 128, 200));
    
    m_coverageRectIndicatorLayer.get().setName("coverage indicator");
    m_coverageRectIndicatorLayer.get().setAnchorPoint(FloatPoint3D());
    m_coverageRectIndicatorLayer.get().setBackgroundColor(Color(64, 64, 64, 50));

    m_layer.get().appendSublayer(m_coverageRectIndicatorLayer);
    m_layer.get().appendSublayer(m_visibleViewportIndicatorLayer);
    
    if (m_controller.layoutViewportRect())
        m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);

    update();
}

TileCoverageMap::~TileCoverageMap()
{
    m_layer.get().setOwner(nullptr);
}

void TileCoverageMap::setNeedsUpdate()
{
    if (!m_updateTimer.isActive())
        m_updateTimer.startOneShot(0_s);
}

void TileCoverageMap::updateTimerFired()
{
    update();
}

void TileCoverageMap::update()
{
    FloatRect containerBounds = m_controller.bounds();
    FloatRect visibleRect = m_controller.visibleRect();
    FloatRect coverageRect = m_controller.coverageRect();
    visibleRect.contract(4, 4); // Layer is positioned 2px from top and left edges.

    float widthScale = 1;
    float scale = 1;
    if (!containerBounds.isEmpty()) {
        widthScale = std::min<float>(visibleRect.width() / containerBounds.width(), 0.1);
        float visibleHeight = visibleRect.height() - std::min(m_controller.topContentInset(), visibleRect.y());
        scale = std::min(widthScale, visibleHeight / containerBounds.height());
    }

    float indicatorScale = scale * m_controller.tileGrid().scale();

    FloatRect mapBounds = containerBounds;
    mapBounds.scale(indicatorScale);

    m_layer.get().setPosition(m_position + FloatPoint(2, 2));
    m_layer.get().setBounds(mapBounds);
    m_layer.get().setNeedsDisplay();

    visibleRect.scale(indicatorScale);
    visibleRect.expand(2, 2);
    m_visibleViewportIndicatorLayer->setPosition(visibleRect.location());
    m_visibleViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), visibleRect.size()));

    if (auto layoutViewportRect = m_controller.layoutViewportRect()) {
        FloatRect layoutRect = layoutViewportRect.value();
        layoutRect.scale(indicatorScale);
        layoutRect.expand(2, 2);
        m_layoutViewportIndicatorLayer->setPosition(layoutRect.location());
        m_layoutViewportIndicatorLayer->setBounds(FloatRect(FloatPoint(), layoutRect.size()));

        if (!m_layoutViewportIndicatorLayer->superlayer())
            m_layer.get().appendSublayer(m_layoutViewportIndicatorLayer);
    } else if (m_layoutViewportIndicatorLayer->superlayer())
        m_layoutViewportIndicatorLayer->removeFromSuperlayer();

    coverageRect.scale(indicatorScale);
    coverageRect.expand(2, 2);
    m_coverageRectIndicatorLayer->setPosition(coverageRect.location());
    m_coverageRectIndicatorLayer->setBounds(FloatRect(FloatPoint(), coverageRect.size()));

    Color visibleRectIndicatorColor;
    switch (m_controller.indicatorMode()) {
    case SynchronousScrollingBecauseOfLackOfScrollingCoordinatorIndication:
        visibleRectIndicatorColor = Color(200, 80, 255);
        break;
    case SynchronousScrollingBecauseOfStyleIndication:
        visibleRectIndicatorColor = Color(255, 0, 0);
        break;
    case SynchronousScrollingBecauseOfEventHandlersIndication:
        visibleRectIndicatorColor = Color(255, 255, 0);
        break;
    case AsyncScrollingIndication:
        visibleRectIndicatorColor = Color(0, 200, 0);
        break;
    }

    m_visibleViewportIndicatorLayer.get().setBorderColor(visibleRectIndicatorColor);
}

void TileCoverageMap::platformCALayerPaintContents(PlatformCALayer* platformCALayer, GraphicsContext& context, const FloatRect&, GraphicsLayerPaintBehavior)
{
    ASSERT_UNUSED(platformCALayer, platformCALayer == m_layer.ptr());
    m_controller.tileGrid().drawTileMapContents(context.platformContext(), m_layer.get().bounds());
}

float TileCoverageMap::platformCALayerDeviceScaleFactor() const
{
    return m_controller.rootLayer().owner()->platformCALayerDeviceScaleFactor();
}

void TileCoverageMap::setDeviceScaleFactor(float deviceScaleFactor)
{
    m_layer.get().setContentsScale(deviceScaleFactor);
}

}
