/*
 * Copyright (C) 2018 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.MediaTimelineOverviewGraph = class MediaTimelineOverviewGraph extends WI.TimelineOverviewGraph
{
    constructor(timeline, timelineOverview)
    {
        console.assert(timeline instanceof WI.Timeline);
        console.assert(timeline.type === WI.TimelineRecord.Type.Media);

        super(timelineOverview);

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

        this.reset();

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

        timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._handleRecordAdded, this);
        timeline.addEventListener(WI.Timeline.Event.TimesUpdated, this._handleTimesUpdated, this);
    }

    // Static

    static get maximumRowCount() {
        return 6;
    }

    // Public

    reset()
    {
        super.reset();

        this._recordsWithoutStartTime = new Set;

        this.element.removeChildren();

        this._nextDumpRow = 0;
        this._timelineRecordGridRows = [];

        for (let i = 0; i < MediaTimelineOverviewGraph.maximumRowCount; ++i) {
            let rowElement = this.element.appendChild(document.createElement("div"));
            rowElement.className = "graph-row";

            this._timelineRecordGridRows.push({
                records: [],
                recordBars: [],
                element: rowElement,
            });
        }
    }

    // Protected

    layout()
    {
        if (!this.visible)
            return;

        let secondsPerPixel = this.timelineOverview.secondsPerPixel;
        let recordBarIndex = 0;

        let createBar = (element, recordBars, records, renderMode) => {
            let timelineRecordBar = recordBars[recordBarIndex];
            if (!timelineRecordBar)
                timelineRecordBar = recordBars[recordBarIndex] = new WI.TimelineRecordBar(this, records, renderMode);
            else {
                timelineRecordBar.renderMode = renderMode;
                timelineRecordBar.records = records;
            }
            timelineRecordBar.refresh(this);
            if (!timelineRecordBar.element.parentNode)
                element.appendChild(timelineRecordBar.element);
            ++recordBarIndex;
        };

        for (let {records, recordBars, element} of this._timelineRecordGridRows) {
            recordBarIndex = 0;

            WI.TimelineRecordBar.createCombinedBars(records, secondsPerPixel, this, createBar.bind(this, element, recordBars));

            // Remove the remaining unused `WI.TimelineRecordBar`.
            for (; recordBarIndex < recordBars.length; ++recordBarIndex) {
                recordBars[recordBarIndex].records = null;
                recordBars[recordBarIndex].element.remove();
            }
        }
    }

    updateSelectedRecord()
    {
        super.updateSelectedRecord();

        for (let {recordBars} of this._timelineRecordGridRows) {
            for (let recordBar of recordBars) {
                if (recordBar.records.includes(this.selectedRecord)) {
                    this.selectedRecordBar = recordBar;
                    return;
                }
            }
        }

        this.selectedRecordBar = null;
    }

    // Private

    _processRecord(record)
    {
        console.assert(record instanceof WI.MediaTimelineRecord);

        if (isNaN(record.startTime)) {
            this._recordsWithoutStartTime.add(record);
            record.singleFireEventListener(WI.TimelineRecord.Event.Updated, (event) => {
                this._processRecord(record);

                this.needsLayout();
            });
            return;
        }

        this._recordsWithoutStartTime.delete(record);

        function compareByStartTime(a, b) {
            return a.startTime - b.startTime;
        }

        let minimumBarPaddingTime = WI.TimelineOverview.MinimumDurationPerPixel * (WI.TimelineRecordBar.MinimumWidthPixels + WI.TimelineRecordBar.MinimumMarginPixels);

        // Try to find a row that has room and does not overlap a previous record.
        for (let i = 0; i < this._timelineRecordGridRows.length; ++i) {
            let records = this._timelineRecordGridRows[i].records;
            let lastRecord = records.lastValue;
            if (!lastRecord || lastRecord.endTime + minimumBarPaddingTime <= record.startTime) {
                insertObjectIntoSortedArray(record, records, compareByStartTime);
                this._nextDumpRow = i + 1;
                return;
            }
        }

        // Try to find a row that does not overlap a previous record's active time, but it can overlap the inactive time.
        for (let i = 0; i < this._timelineRecordGridRows.length; ++i) {
            let records = this._timelineRecordGridRows[i].records;
            let lastRecord = records.lastValue;
            console.assert(lastRecord);
            if (lastRecord.usesActiveStartTime && lastRecord.activeStartTime + minimumBarPaddingTime <= record.startTime) {
                insertObjectIntoSortedArray(record, records, compareByStartTime);
                this._nextDumpRow = i + 1;
                break;
            }
        }

        // We didn't find a empty spot, so dump into the designated dump row.
        if (this._nextDumpRow >= MediaTimelineOverviewGraph.maximumRowCount)
            this._nextDumpRow = 0;
        insertObjectIntoSortedArray(record, this._timelineRecordGridRows[this._nextDumpRow++].records, compareByStartTime);
    }

    _handleRecordAdded(event)
    {
        this._processRecord(event.data.record);

        this.needsLayout();
    }

    _handleTimesUpdated(event)
    {
        this.needsLayout();
    }
};
