/*
 * Copyright (C) 2016 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.
 */

WI.MemoryTimelineView = class MemoryTimelineView extends WI.TimelineView
{
    constructor(timeline, extraArguments)
    {
        super(timeline, extraArguments);

        this._recording = extraArguments.recording;

        console.assert(timeline.type === WI.TimelineRecord.Type.Memory, timeline);

        this.element.classList.add("memory");

        let contentElement = this.element.appendChild(document.createElement("div"));
        contentElement.classList.add("content");

        let overviewElement = contentElement.appendChild(document.createElement("div"));
        overviewElement.classList.add("overview");

        function createChartContainer(parentElement, subtitle, tooltip) {
            let chartElement = parentElement.appendChild(document.createElement("div"));
            chartElement.classList.add("chart");

            let chartSubtitleElement = chartElement.appendChild(document.createElement("div"));
            chartSubtitleElement.classList.add("subtitle");
            chartSubtitleElement.textContent = subtitle;
            chartSubtitleElement.title = tooltip;

            let chartFlexContainerElement = chartElement.appendChild(document.createElement("div"));
            chartFlexContainerElement.classList.add("container");
            return chartFlexContainerElement;
        }

        let usageTooltip = WI.UIString("Breakdown of each memory category at the end of the selected time range");
        let usageChartContainerElement = createChartContainer(overviewElement, WI.UIString("Breakdown"), usageTooltip);
        this._usageCircleChart = new WI.CircleChart({size: 120, innerRadiusRatio: 0.5});
        this.addSubview(this._usageCircleChart);
        usageChartContainerElement.appendChild(this._usageCircleChart.element);
        this._usageLegendElement = usageChartContainerElement.appendChild(document.createElement("div"));
        this._usageLegendElement.classList.add("legend", "usage");

        let dividerElement = overviewElement.appendChild(document.createElement("div"));
        dividerElement.classList.add("divider");

        let maxComparisonTooltip = WI.UIString("Comparison of total memory size at the end of the selected time range to the maximum memory size in this recording");
        let maxComparisonChartContainerElement = createChartContainer(overviewElement, WI.UIString("Max Comparison"), maxComparisonTooltip);
        this._maxComparisonCircleChart = new WI.CircleChart({size: 120, innerRadiusRatio: 0.5});
        this.addSubview(this._maxComparisonCircleChart);
        maxComparisonChartContainerElement.appendChild(this._maxComparisonCircleChart.element);
        this._maxComparisonLegendElement = maxComparisonChartContainerElement.appendChild(document.createElement("div"));
        this._maxComparisonLegendElement.classList.add("legend", "maximum");

        let detailsContainerElement = this._detailsContainerElement = contentElement.appendChild(document.createElement("div"));
        detailsContainerElement.classList.add("details");

        this._timelineRuler = new WI.TimelineRuler;
        this.addSubview(this._timelineRuler);
        detailsContainerElement.appendChild(this._timelineRuler.element);

        let detailsSubtitleElement = detailsContainerElement.appendChild(document.createElement("div"));
        detailsSubtitleElement.classList.add("subtitle");
        detailsSubtitleElement.textContent = WI.UIString("Categories");

        this._didInitializeCategories = false;
        this._categoryViews = [];
        this._usageLegendSizeElementMap = new Map;

        this._maxSize = 0;
        this._maxComparisonMaximumSizeElement = null;
        this._maxComparisonCurrentSizeElement = null;

        timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._memoryTimelineRecordAdded, this);

        this.element.addEventListener("mousemove", this._handleGraphMouseMove.bind(this));

        for (let record of timeline.records)
            this._processRecord(record);
    }

    // Static

    static displayNameForCategory(category)
    {
        switch (category) {
        case WI.MemoryCategory.Type.JavaScript:
            return WI.UIString("JavaScript");
        case WI.MemoryCategory.Type.Images:
            return WI.UIString("Images");
        case WI.MemoryCategory.Type.Layers:
            return WI.UIString("Layers");
        case WI.MemoryCategory.Type.Page:
            return WI.UIString("Page");
        }
    }

    static get memoryCategoryViewHeight() { return 75; }

    // Public

    shown()
    {
        super.shown();

        this._timelineRuler.updateLayout(WI.View.LayoutReason.Resize);
    }

    closed()
    {
        console.assert(this.representedObject instanceof WI.Timeline);
        this.representedObject.removeEventListener(null, null, this);
    }

    reset()
    {
        super.reset();

        this._maxSize = 0;

        this.clear();
    }

    clear()
    {
        this._cachedLegendRecord = null;
        this._cachedLegendMaxSize = undefined;
        this._cachedLegendCurrentSize = undefined;

        this._usageCircleChart.clear();
        this._usageCircleChart.needsLayout();
        this._clearUsageLegend();

        this._maxComparisonCircleChart.clear();
        this._maxComparisonCircleChart.needsLayout();
        this._clearMaxComparisonLegend();

        for (let categoryView of this._categoryViews)
            categoryView.clear();
    }

    get scrollableElements()
    {
        return [this.element];
    }

    // Protected

    get showsFilterBar() { return false; }

    initialLayout()
    {
        super.initialLayout();

        this.element.style.setProperty("--memory-category-view-height", MemoryTimelineView.memoryCategoryViewHeight + "px");
    }

    layout()
    {
        if (this.layoutReason === WI.View.LayoutReason.Resize)
            return;

        // Always update timeline ruler.
        this._timelineRuler.zeroTime = this.zeroTime;
        this._timelineRuler.startTime = this.startTime;
        this._timelineRuler.endTime = this.endTime;

        if (!this._didInitializeCategories)
            return;

        let graphStartTime = this.startTime;
        let graphEndTime = this.endTime;
        let secondsPerPixel = this._timelineRuler.secondsPerPixel;
        let visibleEndTime = Math.min(this.endTime, this.currentTime);

        let discontinuities = this._recording.discontinuitiesInTimeRange(graphStartTime, visibleEndTime);

        let visibleRecords = this.representedObject.recordsInTimeRange(graphStartTime, visibleEndTime, {
            includeRecordBeforeStart: !discontinuities.length || discontinuities[0].startTime > graphStartTime,
            includeRecordAfterEnd: true,
        });
        if (!visibleRecords.length || (visibleRecords.length === 1 && visibleRecords[0].endTime < graphStartTime)) {
            this.clear();
            return;
        }

        // Update total usage chart with the last record's data.
        let lastRecord = visibleRecords.lastValue;
        let values = [];
        for (let {size} of lastRecord.categories)
            values.push(size);
        this._usageCircleChart.values = values;
        this._usageCircleChart.updateLayout();
        this._updateUsageLegend(lastRecord);

        // Update maximum comparison chart.
        this._maxComparisonCircleChart.values = [lastRecord.totalSize, this._maxSize - lastRecord.totalSize];
        this._maxComparisonCircleChart.updateLayout();
        this._updateMaxComparisonLegend(lastRecord.totalSize);

        let categoryDataMap = {};
        for (let categoryView of this._categoryViews)
            categoryDataMap[categoryView.category] = {dataPoints: [], max: -Infinity, min: Infinity};

        for (let record of visibleRecords) {
            let time = record.startTime;
            let startDiscontinuity = null;
            let endDiscontinuity = null;
            if (discontinuities.length && discontinuities[0].endTime <= time) {
                startDiscontinuity = discontinuities.shift();
                endDiscontinuity = startDiscontinuity;
                while (discontinuities.length && discontinuities[0].endTime <= time)
                    endDiscontinuity = discontinuities.shift();
            }

            for (let category of record.categories) {
                let categoryData = categoryDataMap[category.type];

                if (startDiscontinuity) {
                    if (categoryData.dataPoints.length) {
                        let previousDataPoint = categoryData.dataPoints.lastValue;
                        categoryData.dataPoints.push({time: startDiscontinuity.startTime, size: previousDataPoint.size});
                    }

                    categoryData.dataPoints.push({time: startDiscontinuity.startTime, size: 0});
                    categoryData.dataPoints.push({time: endDiscontinuity.endTime, size: 0});
                    categoryData.dataPoints.push({time: endDiscontinuity.endTime, size: category.size});
                }

                categoryData.dataPoints.push({time, size: category.size});
                categoryData.max = Math.max(categoryData.max, category.size);
                categoryData.min = Math.min(categoryData.min, category.size);
            }
        }

        // If the graph end time is inside a gap, the last data point should
        // only be extended to the start of the discontinuity.
        if (discontinuities.length)
            visibleEndTime = discontinuities[0].startTime;

        function layoutCategoryView(categoryView, {dataPoints, min, max}) {
            if (min === Infinity)
                min = 0;
            if (max === -Infinity)
                max = 0;

            // Zoom in to the top of each graph to accentuate small changes.
            let graphMin = min * 0.95;
            let graphMax = (max * 1.05) - graphMin;

            function xScale(time) {
                return (time - graphStartTime) / secondsPerPixel;
            }

            let size = new WI.Size(xScale(graphEndTime), MemoryTimelineView.memoryCategoryViewHeight);

            function yScale(value) {
                return size.height - (((value - graphMin) / graphMax) * size.height);
            }

            categoryView.updateChart(dataPoints, size, visibleEndTime, min, max, xScale, yScale);
        }

        for (let categoryView of this._categoryViews)
            layoutCategoryView(categoryView, categoryDataMap[categoryView.category]);
    }

    // Private

    _graphPositionForMouseEvent(event)
    {
        let chartElement = event.target.closest(".area-chart, .stacked-area-chart, .range-chart");
        if (!chartElement)
            return NaN;

        let chartRect = chartElement.getBoundingClientRect();
        let position = event.pageX - chartRect.left;

        if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL)
            return chartRect.width - position;
        return position;
    }

    _handleGraphMouseMove(event)
    {
        let mousePosition = this._graphPositionForMouseEvent(event);
        if (isNaN(mousePosition)) {
            this.dispatchEventToListeners(WI.TimelineView.Event.ScannerHide);
            return;
        }

        let secondsPerPixel = this._timelineRuler.secondsPerPixel;
        let time = this.startTime + (mousePosition * secondsPerPixel);

        this.dispatchEventToListeners(WI.TimelineView.Event.ScannerShow, {time});
    }

    _clearUsageLegend()
    {
        for (let sizeElement of this._usageLegendSizeElementMap.values())
            sizeElement.textContent = emDash;

        let totalElement = this._usageCircleChart.centerElement.firstChild;
        if (totalElement) {
            totalElement.firstChild.textContent = "";
            totalElement.lastChild.textContent = "";
        }
    }

    _updateUsageLegend(record)
    {
        if (this._cachedLegendRecord === record)
            return;

        this._cachedLegendRecord = record;

        for (let {type, size} of record.categories) {
            let sizeElement = this._usageLegendSizeElementMap.get(type);
            sizeElement.textContent = Number.isFinite(size) ? Number.bytesToString(size) : emDash;
        }

        let centerElement = this._usageCircleChart.centerElement;
        let totalElement = centerElement.firstChild;
        if (!totalElement) {
            totalElement = centerElement.appendChild(document.createElement("div"));
            totalElement.classList.add("total-usage");
            totalElement.appendChild(document.createElement("span")); // firstChild
            totalElement.appendChild(document.createElement("br"));
            totalElement.appendChild(document.createElement("span")); // lastChild
        }

        let totalSize = Number.bytesToString(record.totalSize).split(/\s+/);
        totalElement.firstChild.textContent = totalSize[0];
        totalElement.lastChild.textContent = totalSize[1];
    }

    _clearMaxComparisonLegend()
    {
        if (this._maxComparisonMaximumSizeElement)
            this._maxComparisonMaximumSizeElement.textContent = emDash;
        if (this._maxComparisonCurrentSizeElement)
            this._maxComparisonCurrentSizeElement.textContent = emDash;

        let totalElement = this._maxComparisonCircleChart.centerElement.firstChild;
        if (totalElement)
            totalElement.textContent = "";
    }

    _updateMaxComparisonLegend(currentSize)
    {
        if (this._cachedLegendMaxSize === this._maxSize && this._cachedLegendCurrentSize === currentSize)
            return;

        this._cachedLegendMaxSize = this._maxSize;
        this._cachedLegendCurrentSize = currentSize;

        this._maxComparisonMaximumSizeElement.textContent = Number.isFinite(this._maxSize) ? Number.bytesToString(this._maxSize) : emDash;
        this._maxComparisonCurrentSizeElement.textContent = Number.isFinite(currentSize) ? Number.bytesToString(currentSize) : emDash;

        let centerElement = this._maxComparisonCircleChart.centerElement;
        let totalElement = centerElement.firstChild;
        if (!totalElement) {
            totalElement = centerElement.appendChild(document.createElement("div"));
            totalElement.classList.add("max-percentage");
        }

        // The chart will only show a perfect circle if the current and max are really the same value.
        // So do a little massaging to ensure 0.9995 doesn't get rounded up to 1.
        let percent = currentSize / this._maxSize;
        totalElement.textContent = Number.percentageString(percent === 1 ? percent : (percent - 0.0005));
    }

    _initializeCategoryViews(record)
    {
        console.assert(!this._didInitializeCategories, "Should only initialize category views once");
        this._didInitializeCategories = true;

        let segments = [];
        let lastCategoryViewElement = null;

        function appendLegendRow(legendElement, swatchClass, label, tooltip) {
            let rowElement = legendElement.appendChild(document.createElement("div"));
            rowElement.classList.add("row");

            let swatchElement = rowElement.appendChild(document.createElement("div"));
            swatchElement.classList.add("swatch", swatchClass);

            let valueContainer = rowElement.appendChild(document.createElement("div"));
            valueContainer.classList.add("value");

            let labelElement = valueContainer.appendChild(document.createElement("div"));
            labelElement.classList.add("label");
            labelElement.textContent = label;

            let sizeElement = valueContainer.appendChild(document.createElement("div"));
            sizeElement.classList.add("size");

            if (tooltip)
                rowElement.title = tooltip;

            return sizeElement;
        }

        for (let {type} of record.categories) {
            segments.push(type);

            // Per-category graph.
            let categoryView = new WI.MemoryCategoryView(type, WI.MemoryTimelineView.displayNameForCategory(type));
            this._categoryViews.push(categoryView);
            this.addSubview(categoryView);
            if (!lastCategoryViewElement)
                this._detailsContainerElement.appendChild(categoryView.element);
            else
                this._detailsContainerElement.insertBefore(categoryView.element, lastCategoryViewElement);
            lastCategoryViewElement = categoryView.element;

            // Usage legend rows.
            let sizeElement = appendLegendRow.call(this, this._usageLegendElement, type, WI.MemoryTimelineView.displayNameForCategory(type));
            this._usageLegendSizeElementMap.set(type, sizeElement);
        }

        this._usageCircleChart.segments = segments;

        // Max comparison legend rows.
        this._maxComparisonCircleChart.segments = ["current", "remainder"];
        this._maxComparisonMaximumSizeElement = appendLegendRow.call(this, this._maxComparisonLegendElement, "remainder", WI.UIString("Maximum"), WI.UIString("Maximum maximum memory size in this recording"));
        this._maxComparisonCurrentSizeElement = appendLegendRow.call(this, this._maxComparisonLegendElement, "current", WI.UIString("Current"), WI.UIString("Total memory size at the end of the selected time range"));
    }

    _memoryTimelineRecordAdded(event)
    {
        let memoryTimelineRecord = event.data.record;
        console.assert(memoryTimelineRecord instanceof WI.MemoryTimelineRecord);

        this._processRecord(memoryTimelineRecord);

        if (memoryTimelineRecord.startTime >= this.startTime && memoryTimelineRecord.endTime <= this.endTime)
            this.needsLayout();
    }

    _processRecord(memoryTimelineRecord)
    {
        if (!this._didInitializeCategories)
            this._initializeCategoryViews(memoryTimelineRecord);

        this._maxSize = Math.max(this._maxSize, memoryTimelineRecord.totalSize);
    }
};
