/*
 * Copyright (C) 2017 Igalia S.L.
 *
 * 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 "ResourceUsageOverlay.h"

#if ENABLE(RESOURCE_USAGE) && OS(LINUX)

#include "Chrome.h"
#include "ChromeClient.h"
#include "CommonVM.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "ResourceUsageThread.h"
#include "SystemFontDatabase.h"
#include <JavaScriptCore/VM.h>
#include <wtf/text/StringConcatenateNumbers.h>

namespace WebCore {

static ResourceUsageData gData;

static String cpuUsageString(float cpuUsage)
{
    if (cpuUsage < 0)
        return "<unknown>"_s;
    return makeString(FormattedNumber::fixedWidth(cpuUsage, 1), '%');
}

static String formatByteNumber(size_t number)
{
    if (number >= 1024 * 1048576)
        return makeString(FormattedNumber::fixedWidth(number / (1024. * 1048576), 3), " GB");
    if (number >= 1048576)
        return makeString(FormattedNumber::fixedWidth(number / 1048576., 2), " MB");
    if (number >= 1024)
        return makeString(FormattedNumber::fixedWidth(number / 1024, 1), " kB");
    return String::number(number);
}

static String gcTimerString(MonotonicTime timerFireDate, MonotonicTime now)
{
    if (std::isnan(timerFireDate))
        return "[not scheduled]"_s;
    return String::numberToStringFixedPrecision((timerFireDate - now).seconds());
}

static const float gFontSize = 14;

class ResourceUsageOverlayPainter final : public GraphicsLayerClient {
    WTF_MAKE_FAST_ALLOCATED;
public:
    ResourceUsageOverlayPainter(ResourceUsageOverlay& overlay)
        : m_overlay(overlay)
    {
        auto& systemFontDatabase = SystemFontDatabase::singleton();
        auto messageBox = SystemFontDatabase::FontShorthand::MessageBox;
        FontCascadeDescription fontDescription;
        fontDescription.setOneFamily(systemFontDatabase.systemFontShorthandFamily(messageBox));
        fontDescription.setWeight(systemFontDatabase.systemFontShorthandWeight(messageBox));
        fontDescription.setComputedSize(gFontSize);
        m_textFont = FontCascade(WTFMove(fontDescription), 0, 0);
        m_textFont.update(nullptr);
    }

    ~ResourceUsageOverlayPainter() = default;

private:
    void paintContents(const GraphicsLayer*, GraphicsContext& context, const FloatRect& clip, GraphicsLayerPaintBehavior) override
    {
        GraphicsContextStateSaver stateSaver(context);
        context.fillRect(clip, Color::black.colorWithAlphaByte(204));
        context.setFillColor(SRGBA<uint8_t> { 230, 230, 230 });

        FloatPoint position = { 10, 20 };
        String string =  "CPU: " + cpuUsageString(gData.cpu);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        string = "Memory: " + formatByteNumber(gData.totalDirtySize);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        string = "External: " + formatByteNumber(gData.totalExternalSize);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        string = "GC Heap: " + formatByteNumber(gData.categories[MemoryCategory::GCHeap].dirtySize);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        string = "GC owned: " + formatByteNumber(gData.categories[MemoryCategory::GCOwned].dirtySize);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        MonotonicTime now = MonotonicTime::now();
        string = "Eden GC: " + gcTimerString(gData.timeOfNextEdenCollection, now);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);

        string = "Full GC: " + gcTimerString(gData.timeOfNextFullCollection, now);
        context.drawText(m_textFont, TextRun(string), position);
        position.move(0, gFontSize + 2);
    }

    void notifyFlushRequired(const GraphicsLayer*) override
    {
        m_overlay.overlay().page()->scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush);
    }

    ResourceUsageOverlay& m_overlay;
    FontCascade m_textFont;
};

void ResourceUsageOverlay::platformInitialize()
{
    m_overlayPainter = makeUnique<ResourceUsageOverlayPainter>(*this);
    m_paintLayer = GraphicsLayer::create(overlay().page()->chrome().client().graphicsLayerFactory(), *m_overlayPainter);
    m_paintLayer->setAnchorPoint(FloatPoint3D());
    m_paintLayer->setSize({ normalWidth, normalHeight });
    m_paintLayer->setBackgroundColor(Color::black.colorWithAlphaByte(204));
    m_paintLayer->setDrawsContent(true);
    overlay().layer().addChild(*m_paintLayer);

    ResourceUsageThread::addObserver(this, All, [this] (const ResourceUsageData& data) {
        gData = data;
        m_paintLayer->setNeedsDisplay();
    });
}

void ResourceUsageOverlay::platformDestroy()
{
    ResourceUsageThread::removeObserver(this);
    if (!m_paintLayer)
        return;

    m_paintLayer->removeFromParent();
    m_paintLayer = nullptr;
    m_overlayPainter = nullptr;
}

} // namespace WebCore

#endif // ENABLE(RESOURCE_USAGE) && OS(LINUX)
