// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/mojo/url/mojom/origin.mojom-webui.js';
import { assert, assertNotReached } from 'chrome://resources/js/assert.js';
import { PromiseResolver } from 'chrome://resources/js/promise_resolver.js';
import { MediaEngagementScoreDetailsProvider } from './media_engagement_score_details.mojom-webui.js';
// Allow a function to be provided by tests, which will be called when
// the page has been populated with media engagement details.
const pageIsPopulatedResolver = new PromiseResolver();
function whenPageIsPopulatedForTest() {
    return pageIsPopulatedResolver.promise;
}
Object.assign(window, { whenPageIsPopulatedForTest });
let detailsProvider = null;
let info = null;
let engagementTableBody = null;
let sortReverse = true;
let sortKey = 'totalScore';
let configTableBody = null;
let showNoPlaybacks = false;
/**
 * Creates a single row in the engagement table.
 */
function createRow(rowInfo) {
    const template = document.querySelector('#datarow');
    assert(template);
    const td = template.content.querySelectorAll('td');
    td[0].textContent = rowInfo.origin.scheme + '://' + rowInfo.origin.host;
    if (rowInfo.origin.scheme === 'http' && rowInfo.origin.port !== 80) {
        td[0].textContent += ':' + rowInfo.origin.port;
    }
    else if (rowInfo.origin.scheme === 'https' && rowInfo.origin.port !== 443) {
        td[0].textContent += ':' + rowInfo.origin.port;
    }
    td[1].textContent = rowInfo.visits.toString();
    td[2].textContent = rowInfo.mediaPlaybacks.toString();
    td[3].textContent = rowInfo.lastMediaPlaybackTime ?
        new Date(rowInfo.lastMediaPlaybackTime).toISOString() :
        '';
    td[4].textContent = rowInfo.isHigh ? 'Yes' : 'No';
    td[5].textContent = rowInfo.totalScore ? rowInfo.totalScore.toFixed(2) : '0';
    td[6].querySelectorAll('.engagement-bar')[0].style.width =
        (rowInfo.totalScore * 50) + 'px';
    return document.importNode(template.content, true);
}
/**
 * Remove all rows from the engagement table.
 */
function clearTable() {
    assert(engagementTableBody);
    engagementTableBody.innerHTML =
        window.trustedTypes ? window.trustedTypes.emptyHTML : '';
}
/**
 * Sort the engagement info based on |sortKey| and |sortReverse|.
 */
function sortInfo() {
    assert(info);
    info.sort((a, b) => {
        return (sortReverse ? -1 : 1) * compareTableItem(sortKey, a, b);
    });
}
/**
 * Compares two MediaEngagementScoreDetails objects based on |sortKey|.
 * @param sortKey The name of the property to sort by.
 * @param a The first object to compare.
 * @param b The second object to compare.
 * @return A negative number if |a| should be ordered before
 *     |b|, a positive number otherwise.
 */
function compareTableItem(sortKey, a, b) {
    // Compare the hosts of the origin ignoring schemes.
    if (sortKey === 'origin') {
        return a.origin.host > b.origin.host ? 1 : -1;
    }
    if (sortKey === 'visits' || sortKey === 'mediaPlaybacks' ||
        sortKey === 'lastMediaPlaybackTime' || sortKey === 'totalScore' ||
        sortKey === 'isHigh') {
        const val1 = a[sortKey];
        const val2 = b[sortKey];
        return val1 - val2;
    }
    assertNotReached('Unsupported sort key: ' + sortKey);
}
/**
 * Creates a single row in the config table.
 * @param name The name of the config setting.
 * @param value The value of the config setting.
 */
function createConfigRow(name, value) {
    const template = document.querySelector('#configrow');
    assert(template);
    const td = template.content.querySelectorAll('td');
    td[0].textContent = name;
    td[1].textContent = value.toString();
    return document.importNode(template.content, true);
}
/**
 * Regenerates the config table.
 * @param config The config of the MEI service.
 */
function renderConfigTable(config) {
    assert(configTableBody);
    configTableBody.innerHTML =
        window.trustedTypes ? (window.trustedTypes.emptyHTML) : '';
    configTableBody.appendChild(createConfigRow('Min Sessions', config.scoreMinVisits));
    configTableBody.appendChild(createConfigRow('Lower Threshold', config.highScoreLowerThreshold));
    configTableBody.appendChild(createConfigRow('Upper Threshold', config.highScoreUpperThreshold));
    configTableBody.appendChild(createConfigRow('Record MEI data', formatFeatureFlag(config.featureRecordData)));
    configTableBody.appendChild(createConfigRow('Bypass autoplay based on MEI', formatFeatureFlag(config.featureBypassAutoplay)));
    configTableBody.appendChild(createConfigRow('Preload MEI data', formatFeatureFlag(config.featurePreloadData)));
    configTableBody.appendChild(createConfigRow('MEI for HTTPS only', formatFeatureFlag(config.featureHttpsOnly)));
    configTableBody.appendChild(createConfigRow('Autoplay disable settings', formatFeatureFlag(config.featureAutoplayDisableSettings)));
    configTableBody.appendChild(createConfigRow('Unified autoplay (preference)', formatFeatureFlag(config.prefDisableUnifiedAutoplay)));
    configTableBody.appendChild(createConfigRow('Custom autoplay policy', formatFeatureFlag(config.hasCustomAutoplayPolicy)));
    configTableBody.appendChild(createConfigRow('Autoplay Policy', config.autoplayPolicy));
    configTableBody.appendChild(createConfigRow('Preload version', config.preloadVersion ? config.preloadVersion : 'Not Available'));
}
/**
 * Converts a boolean into a string value.
 */
function formatFeatureFlag(value) {
    return value ? 'Enabled' : 'Disabled';
}
/**
 * Regenerates the engagement table from |info|.
 */
function renderTable() {
    clearTable();
    sortInfo();
    assert(info);
    assert(engagementTableBody);
    info.filter(rowInfo => (showNoPlaybacks || rowInfo.mediaPlaybacks > 0))
        .forEach(rowInfo => engagementTableBody.appendChild(createRow(rowInfo)));
}
/**
 * Retrieve media engagement info and render the engagement table.
 */
function updateEngagementTable() {
    assert(detailsProvider);
    // Populate engagement table.
    detailsProvider.getMediaEngagementScoreDetails().then(response => {
        info = response.info;
        renderTable();
        pageIsPopulatedResolver.resolve();
    });
    // Populate config settings.
    detailsProvider.getMediaEngagementConfig().then(response => {
        renderConfigTable(response.config);
    });
}
document.addEventListener('DOMContentLoaded', function () {
    detailsProvider = MediaEngagementScoreDetailsProvider.getRemote();
    updateEngagementTable();
    engagementTableBody =
        document.querySelector('#engagement-table-body');
    configTableBody = document.querySelector('#config-table-body');
    // Set table header sort handlers.
    const engagementTableHeader = document.querySelector('#engagement-table-header');
    assert(engagementTableHeader);
    const headers = engagementTableHeader.children;
    for (let i = 0; i < headers.length; i++) {
        headers[i].addEventListener('click', (e) => {
            const target = e.target;
            const newSortKey = target.getAttribute('sort-key');
            if (sortKey === newSortKey) {
                sortReverse = !sortReverse;
            }
            else {
                assert(newSortKey);
                sortKey = newSortKey;
                sortReverse = false;
            }
            const oldSortColumn = document.querySelector('.sort-column');
            assert(oldSortColumn);
            oldSortColumn.classList.remove('sort-column');
            target.classList.add('sort-column');
            if (sortReverse) {
                target.setAttribute('sort-reverse', '');
            }
            else {
                target.removeAttribute('sort-reverse');
            }
            renderTable();
        });
    }
    // Add handler to 'copy all to clipboard' button
    const copyAllToClipboardButton = document.querySelector('#copy-all-to-clipboard');
    assert(copyAllToClipboardButton);
    copyAllToClipboardButton.addEventListener('click', () => {
        // Make sure nothing is selected
        window.getSelection().removeAllRanges();
        document.execCommand('selectAll');
        document.execCommand('copy');
        // And deselect everything at the end.
        window.getSelection().removeAllRanges();
    });
    // Add handler to 'show no playbacks' checkbox
    const showNoPlaybacksCheckbox = document.querySelector('#show-no-playbacks');
    assert(showNoPlaybacksCheckbox);
    showNoPlaybacksCheckbox.addEventListener('change', (e) => {
        showNoPlaybacks = e.target.checked;
        renderTable();
    });
});
