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

var ui = ui || {};
ui.results = ui.results || {};

(function(){

var kResultsPrefetchDelayMS = 500;

// FIXME: Rather than using table, should we be using something fancier?
ui.results.Comparison = base.extends('table', {
    init: function()
    {
        this.className = 'comparison';
        this.innerHTML = '<thead><tr><th>Expected</th><th>Actual</th><th>Diff</th></tr></thead>' +
                         '<tbody><tr><td class="expected result-container"></td><td class="actual result-container"></td><td class="diff result-container"></td></tr></tbody>';
    },
    _selectorForKind: function(kind)
    {
        switch (kind) {
        case results.kExpectedKind:
            return '.expected';
        case results.kActualKind:
            return '.actual';
        case results.kDiffKind:
            return '.diff';
        }
        return '.unknown';
    },
    update: function(kind, result)
    {
        var selector = this._selectorForKind(kind);
        $(selector, this).empty().append(result);
        return result;
    },
});

// We'd really like TextResult and ImageResult to extend a common Result base
// class, but we can't seem to do that because they inherit from different
// HTMLElements. We could have them inherit from <div>, but that seems lame.

ui.results.TextResult = base.extends('iframe', {
    init: function(url)
    {
        this.className = 'text-result';
        this.src = url;
    }
});

ui.results.ImageResult = base.extends('img', {
    init: function(url)
    {
        this.className = 'image-result';
        this.src = url;
    }
});

ui.results.AudioResult = base.extends('audio', {
    init: function(url)
    {
        this.className = 'audio-result';
        this.src = url;
        this.controls = 'controls';
    }
});

function constructorForResultType(type)
{
    if (type == results.kImageType)
        return ui.results.ImageResult;
    if (type == results.kAudioType)
        return ui.results.AudioResult;
    return ui.results.TextResult;
}

ui.results.ResultsGrid = base.extends('div', {
    init: function()
    {
        this.className = 'results-grid';
    },
    _addResult: function(comparison, constructor, resultsURLsByKind, kind)
    {
        var url = resultsURLsByKind[kind];
        if (!url)
            return;
        comparison.update(kind, new constructor(url));
    },
    addComparison: function(resultType, resultsURLsByKind)
    {
        var comparison = new ui.results.Comparison();
        var constructor = constructorForResultType(resultType);

        this._addResult(comparison, constructor, resultsURLsByKind, results.kExpectedKind);
        this._addResult(comparison, constructor, resultsURLsByKind, results.kActualKind);
        this._addResult(comparison, constructor, resultsURLsByKind, results.kDiffKind);

        this.appendChild(comparison);
        return comparison;
    },
    addRow: function(resultType, url)
    {
        var constructor = constructorForResultType(resultType);
        var view = new constructor(url);
        this.appendChild(view);
        return view;
    },
    addResults: function(resultsURLs)
    {
        var resultsURLsByTypeAndKind = {};

        resultsURLsByTypeAndKind[results.kImageType] = {};
        resultsURLsByTypeAndKind[results.kAudioType] = {};
        resultsURLsByTypeAndKind[results.kTextType] = {};

        resultsURLs.forEach(function(url) {
            resultsURLsByTypeAndKind[results.resultType(url)][results.resultKind(url)] = url;
        });

        $.each(resultsURLsByTypeAndKind, function(resultType, resultsURLsByKind) {
            if ($.isEmptyObject(resultsURLsByKind))
                return;
            if (results.kUnknownKind in resultsURLsByKind) {
                // This is something like "crash" that isn't a comparison.
                this.addRow(resultType, resultsURLsByKind[results.kUnknownKind]);
                return;
            }
            this.addComparison(resultType, resultsURLsByKind);
        }.bind(this));

        if (!this.children.length)
            this.textContent = 'No results to display.'
    }
});

ui.results.ResultsDetails = base.extends('div', {
    init: function(delegate, failureInfo)
    {
        this.className = 'results-detail';
        this._delegate = delegate;
        this._failureInfo = failureInfo;
        this._haveShownOnce = false;
    },
    show: function() {
        if (this._haveShownOnce)
            return;
        this._haveShownOnce = true;
        this._delegate.fetchResultsURLs(this._failureInfo, function(resultsURLs) {
            var resultsGrid = new ui.results.ResultsGrid();
            resultsGrid.addResults(resultsURLs);

            $(this).empty().append(
                new ui.actions.List([
                    new ui.actions.Previous(),
                    new ui.actions.Next()
                ])).append(resultsGrid);


        }.bind(this));
    },
});

function isAnyReftest(testName, resultsByTest)
{
    return Object.keys(resultsByTest[testName]).map(function(builder) {
        return resultsByTest[testName][builder];
    }).some(function(resultNode) {
        return resultNode.reftest_type && resultNode.reftest_type.length;
    });
}

ui.results.FlakinessData = base.extends('iframe', {
    init: function()
    {
        this.className = 'flakiness-iframe';
        this.src = ui.urlForEmbeddedFlakinessDashboard();
        this.addEventListener('load', function() {
            window.addEventListener('message', this._handleMessage.bind(this));
        });
    },
    _handleMessage: function(event) {
        if (!this.contentWindow)
            return;

        // Check for null event.origin so that the unittests can get past this point.
        // FIXME: Is this safe? In practice, there's no meaningful harm that can come from
        // a malicious page sending us heightChanged commands, so it doesn't really matter.
        if (event.origin !== 'null' && event.origin != 'https://webkit-test-results.webkit.org') {
            console.log('Invalid origin: ' + event.origin);
            return;
        }

        if (event.data.command != 'heightChanged') {
            console.log('Unknown postMessage command: ' + event.data);
            return;
        }

        this.style.height = event.data.height + 'px';
    }
});

ui.results.TestSelector = base.extends('div', {
    init: function(delegate, resultsByTest)
    {
        this.className = 'test-selector';
        this._delegate = delegate;

        var topPanel = document.createElement('div');
        topPanel.className = 'top-panel';
        this.appendChild(topPanel);

        this._appendResizeHandle();

        var bottomPanel = document.createElement('div');
        bottomPanel.className = 'bottom-panel';
        this.appendChild(bottomPanel);

        this._flakinessData = new ui.results.FlakinessData();
        this.appendChild(this._flakinessData);

        var testNames = Object.keys(resultsByTest);
        testNames.sort().forEach(function(testName) {
            var nonLinkTitle = document.createElement('a');
            nonLinkTitle.classList.add('non-link-title');
            nonLinkTitle.textContent = testName;

            var linkTitle = document.createElement('a');
            linkTitle.classList.add('link-title');
            linkTitle.setAttribute('href', ui.urlForFlakinessDashboard([testName]))
            linkTitle.textContent = testName;

            var header = document.createElement('h3');
            header.appendChild(nonLinkTitle);
            header.appendChild(linkTitle);
            header.addEventListener('click', this._showResults.bind(this, header, false));
            topPanel.appendChild(header);
        }, this);

        // If we have a small amount of content, don't show the resize handler.
        // Otherwise, set the minHeight so that the percentage height of the 
        // topPanel is not too small.
        if (testNames.length <= 4)
            this.removeChild(this.querySelector('.resize-handle'));
        else
            topPanel.style.minHeight = '100px';
    },
    _appendResizeHandle: function()
    {
        var resizeHandle = document.createElement('div');
        resizeHandle.className = 'resize-handle';
        this.appendChild(resizeHandle);

        resizeHandle.addEventListener('mousedown', function(event) {
            this._is_resizing = true;
            event.preventDefault();
        }.bind(this));

        var cancelResize = function(event) { this._is_resizing = false; }.bind(this);
        this.addEventListener('mouseup', cancelResize);
        // FIXME: Use addEventListener once WebKit adds support for mouseleave/mouseenter.
        $(window).bind('mouseleave', cancelResize);

        this.addEventListener('mousemove', function(event) {
            if (!this._is_resizing)
                return;
            var mouseY = event.clientY + document.body.scrollTop - this.offsetTop;
            var percentage = 100 * mouseY / this.offsetHeight;
            document.querySelector('.top-panel').style.maxHeight = percentage + '%';
        }.bind(this))
    },
    _showResults: function(header, scrollInfoView)
    {
        if (!header)
            return false;

        var activeHeader = this.querySelector('.active')
        if (activeHeader)
            activeHeader.classList.remove('active');
        header.classList.add('active');

        var testName = this.currentTestName();
        this._flakinessData.src = ui.urlForEmbeddedFlakinessDashboard([testName]);

        var bottomPanel = this.querySelector('.bottom-panel')
        bottomPanel.innerHTML = '';
        bottomPanel.appendChild(this._delegate.contentForTest(testName));

        var topPanel = this.querySelector('.top-panel');
        if (scrollInfoView) {
            topPanel.scrollTop = header.offsetTop;
            if (header.offsetTop - topPanel.scrollTop < header.offsetHeight)
                topPanel.scrollTop = topPanel.scrollTop - header.offsetHeight;
        }

        var resultsDetails = this.querySelectorAll('.results-detail');
        if (resultsDetails.length)
            resultsDetails[0].show();
        setTimeout(function() {
            Array.prototype.forEach.call(resultsDetails, function(resultsDetail) {
                resultsDetail.show();
            });
        }, kResultsPrefetchDelayMS);

        return true;
    },
    nextResult: function()
    {
        if (this.querySelector('.builder-selector').nextResult())
            return true;
        return this.nextTest();
    },
    previousResult: function()
    {
        if (this.querySelector('.builder-selector').previousResult())
            return true;
        return this.previousTest();
    },
    nextTest: function()
    {
        return this._showResults(this.querySelector('.active').nextSibling, true);
    },
    previousTest: function()
    {
        var succeeded = this._showResults(this.querySelector('.active').previousSibling, true);
        if (succeeded)
            this.querySelector('.builder-selector').lastResult();
        return succeeded;
    },
    firstResult: function()
    {
        this._showResults(this.querySelector('h3'), true);
    },
    currentTestName: function()
    {
        return this.querySelector('.active .non-link-title').textContent;
    }
});

ui.results.BuilderSelector = base.extends('div', {
    init: function(delegate, testName, resultsByBuilder)
    {
        this.className = 'builder-selector';
        this._delegate = delegate;

        var tabStrip = this.appendChild(document.createElement('ul'));

        Object.keys(resultsByBuilder).sort().forEach(function(builderName) {
            var builderHash = base.underscoredBuilderName(builderName);

            var link = document.createElement('a');
            $(link).attr('href', "#" + builderHash).text(ui.displayNameForBuilder(builderName));
            tabStrip.appendChild(document.createElement('li')).appendChild(link);

            var content = this._delegate.contentForTestAndBuilder(testName, builderName);
            content.id = builderHash;
            this.appendChild(content);
        }, this);

        $(this).tabs();
    },
    nextResult: function()
    {
        var nextIndex = $(this).tabs('option', 'selected') + 1;
        if (nextIndex >= $(this).tabs('length'))
            return false
        $(this).tabs('option', 'selected', nextIndex);
        return true;
    },
    previousResult: function()
    {
        var previousIndex = $(this).tabs('option', 'selected') - 1;
        if (previousIndex < 0)
            return false;
        $(this).tabs('option', 'selected', previousIndex);
        return true;
    },
    firstResult: function()
    {
        $(this).tabs('option', 'selected', 0);
    },
    lastResult: function()
    {
        $(this).tabs('option', 'selected', $(this).tabs('length') - 1);
    }
});

ui.results.View = base.extends('div', {
    init: function(delegate)
    {
        this.className = 'results-view';
        this._delegate = delegate;
    },
    contentForTest: function(testName)
    {
        var rebaselineAction;
        if (isAnyReftest(testName, this._resultsByTest))
            rebaselineAction = $('<div class="non-action-button">Reftests cannot be rebaselined. Email webkit-gardening@chromium.org if unsure how to fix this.</div>');
        else
            rebaselineAction = new ui.actions.List([new ui.actions.Rebaseline().makeDefault()]);
        $(rebaselineAction).addClass('rebaseline-action');

        var builderSelector = new ui.results.BuilderSelector(this, testName, this._resultsByTest[testName]);
        $(builderSelector).append(rebaselineAction).append($('<br style="clear:both">'));
        $(builderSelector).bind('tabsselect', function(event, ui) {
            // We will probably have pre-fetched the tab already, but we need to make sure.
            ui.panel.show();
        });
        return builderSelector;
    },
    contentForTestAndBuilder: function(testName, builderName)
    {
        var failureInfo = results.failureInfoForTestAndBuilder(this._resultsByTest, testName, builderName);
        return new ui.results.ResultsDetails(this, failureInfo);
    },
    setResultsByTest: function(resultsByTest)
    {
        $(this).empty();
        this._resultsByTest = resultsByTest;
        this._testSelector = new ui.results.TestSelector(this, resultsByTest);
        this.appendChild(this._testSelector);
    },
    fetchResultsURLs: function(failureInfo, callback)
    {
        this._delegate.fetchResultsURLs(failureInfo, callback)
    },
    nextResult: function()
    {
        return this._testSelector.nextResult();
    },
    previousResult: function()
    {
        return this._testSelector.previousResult();
    },
    nextTest: function()
    {
        return this._testSelector.nextTest();
    },
    previousTest: function()
    {
        return this._testSelector.previousTest();
    },
    firstResult: function()
    {
        this._testSelector.firstResult()
    },
    currentTestName: function()
    {
        return this._testSelector.currentTestName()
    }
});

})();
