class CustomAnalysisTaskConfigurator extends ComponentBase {

    constructor()
    {
        super('custom-analysis-task-configurator');

        this._selectedTests = [];
        this._triggerablePlatforms = [];
        this._selectedPlatform = null;
        this._showComparison = false;
        this._commitSetMap = {};
        this._specifiedRevisions = {'Baseline': new Map, 'Comparison': new Map};
        this._patchUploaders = {'Baseline': new Map, 'Comparison': new Map};
        this._customRootUploaders = {'Baseline': null, 'Comparison': null};
        this._fetchedCommits = {'Baseline': new Map, 'Comparison': new Map};
        this._repositoryGroupByConfiguration = {'Baseline': null, 'Comparison': null};
        this._invalidRevisionsByConfiguration = {'Baseline': new Map, 'Comparison': new Map};

        this._updateTriggerableLazily = new LazilyEvaluatedFunction(this._updateTriggerable.bind(this));
        this._renderTriggerableTestsLazily = new LazilyEvaluatedFunction(this._renderTriggerableTests.bind(this));
        this._renderTriggerablePlatformsLazily = new LazilyEvaluatedFunction(this._renderTriggerablePlatforms.bind(this));
        this._renderRepositoryPanesLazily = new LazilyEvaluatedFunction(this._renderRepositoryPanes.bind(this));
    }

    tests() { return this._selectedTests; }
    platform() { return this._selectedPlatform; }
    commitSets()
    {
        const map = this._commitSetMap;
        if (!map['Baseline'] || !map['Comparison'])
            return null;
        return [map['Baseline'], map['Comparison']];
    }

    selectTests(selectedTests)
    {
        this._selectedTests = selectedTests;

        this._triggerablePlatforms = Triggerable.triggerablePlatformsForTests(this._selectedTests);
        if (this._selectedTests.length && !this._triggerablePlatforms.includes(this._selectedPlatform))
            this._selectedPlatform = null;

        this._didUpdateSelectedPlatforms();
    }

    selectPlatform(selectedPlatform)
    {
        this._selectedPlatform = selectedPlatform;

        const [triggerable, error] = this._updateTriggerableLazily.evaluate(this._selectedTests, this._selectedPlatform);
        this._updateRepositoryGroups(triggerable);

        this._didUpdateSelectedPlatforms();
    }

    _didUpdateSelectedPlatforms()
    {
        for (const configuration of ['Baseline', 'Comparison']) {
            this._updateMapFromSpecifiedRevisionsForConfiguration(this._fetchedCommits, configuration);
            this._updateMapFromSpecifiedRevisionsForConfiguration(this._invalidRevisionsByConfiguration, configuration);
        }
        this._updateCommitSetMap();
        this.dispatchAction('testConfigChange');
        this.enqueueToRender();
    }

    _updateMapFromSpecifiedRevisionsForConfiguration(map, configuration)
    {
        const referenceMap = this._specifiedRevisions[configuration];
        const newValue = new Map;
        for (const [key, value] of map[configuration].entries()) {
            if (!referenceMap.has(key))
                continue;
            newValue.set(key, value);
        }
        if (newValue.size !== map[configuration].size)
            map[configuration] = newValue;
    }

    setCommitSets(baselineCommitSet, comparisonCommitSet)
    {
        const [triggerable, error] = this._updateTriggerableLazily.evaluate(this._selectedTests, this._selectedPlatform);

        if (!triggerable)
            return;

        const baselineRepositoryGroup = triggerable.repositoryGroups().find((repositoryGroup) => repositoryGroup.accepts(baselineCommitSet));
        if (baselineRepositoryGroup) {
            this._repositoryGroupByConfiguration['Baseline'] = baselineRepositoryGroup;
            this._setUploadedFilesToUploader(this._customRootUploaders['Baseline'], baselineCommitSet.customRoots());
            this._specifiedRevisions['Baseline'] = this._revisionMapFromCommitSet(baselineCommitSet);
            this._setPatchFiles('Baseline', baselineCommitSet);
        }

        const comparisonRepositoryGroup = triggerable.repositoryGroups().find((repositoryGroup) => repositoryGroup.accepts(baselineCommitSet));
        if (comparisonRepositoryGroup) {
            this._repositoryGroupByConfiguration['Comparison'] = comparisonRepositoryGroup;
            this._setUploadedFilesToUploader(this._customRootUploaders['Comparison'], comparisonCommitSet.customRoots());
            this._specifiedRevisions['Comparison'] = this._revisionMapFromCommitSet(comparisonCommitSet);
            this._setPatchFiles('Comparison', comparisonCommitSet);
        }

        this._showComparison = true;
        this._updateCommitSetMap();
    }

    _setUploadedFilesToUploader(uploader, files)
    {
        if (!uploader || uploader.hasFileToUpload() || uploader.uploadedFiles().length)
            return;
        uploader.clearUploads();
        for (const uploadedFile of files)
            uploader.addUploadedFile(uploadedFile);
    }

    _setPatchFiles(configurationName, commitSet)
    {
        for (const repository of commitSet.repositories()) {
            const patch = commitSet.patchForRepository(repository);
            if (patch)
                this._setUploadedFilesToUploader(this._ensurePatchUploader(configurationName, repository), [patch]);
        }
    }

    _revisionMapFromCommitSet(commitSet)
    {
        const revisionMap = new Map;
        for (const repository of commitSet.repositories())
            revisionMap.set(repository, commitSet.revisionForRepository(repository));
        return revisionMap;
    }

    didConstructShadowTree()
    {
        this.content('specify-comparison-button').onclick = this.createEventHandler(() => this._configureComparison());

        const createRootUploader = () => {
            const uploader = new InstantFileUploader;
            uploader.allowMultipleFiles();
            uploader.element().textContent = 'Add a new root';
            uploader.listenToAction('removedFile', () => this._updateCommitSetMap());
            return uploader;
        }

        const baselineRootsUploader = createRootUploader();
        baselineRootsUploader.listenToAction('uploadedFile', (uploadedFile) => this._updateCommitSetMap());
        this._customRootUploaders['Baseline'] = baselineRootsUploader;

        const comparisonRootsUploader = createRootUploader();
        comparisonRootsUploader.listenToAction('uploadedFile', () => this._updateCommitSetMap());
        this._customRootUploaders['Comparison'] = comparisonRootsUploader;
    }

    _ensurePatchUploader(configurationName, repository)
    {
        const uploaderMap = this._patchUploaders[configurationName];
        let uploader = uploaderMap.get(repository);
        if (uploader)
            return uploader;

        uploader = new InstantFileUploader;
        uploader.element().textContent = 'Apply a patch';
        uploader.listenToAction('uploadedFile', () => this._updateCommitSetMap());
        uploader.listenToAction('removedFile', () => this._updateCommitSetMap());
        uploaderMap.set(repository, uploader);

        return uploader;
    }

    _configureComparison()
    {
        this._showComparison = true;
        this._repositoryGroupByConfiguration['Comparison'] = this._repositoryGroupByConfiguration['Baseline'];

        const specifiedBaselineRevisions = this._specifiedRevisions['Baseline'];
        const specifiedComparisonRevisions = new Map;
        for (let key of specifiedBaselineRevisions.keys())
            specifiedComparisonRevisions.set(key, specifiedBaselineRevisions.get(key));
        this._specifiedRevisions['Comparison'] = specifiedComparisonRevisions;

        for (const [repository, patchUploader] of this._patchUploaders['Baseline']) {
            const files = patchUploader.uploadedFiles();
            if (!files.length)
                continue;
            const comparisonPatchUploader = this._ensurePatchUploader('Comparison', repository);
            for (const uploadedFile of files)
                comparisonPatchUploader.addUploadedFile(uploadedFile);
        }

        const comparisonRootUploader = this._customRootUploaders['Comparison'];
        for (const uploadedFile of this._customRootUploaders['Baseline'].uploadedFiles())
            comparisonRootUploader.addUploadedFile(uploadedFile);

        this.enqueueToRender();
    }

    render()
    {
        super.render();

        const updateSelectedTestsLazily = this._renderTriggerableTestsLazily.evaluate();
        updateSelectedTestsLazily.evaluate(...this._selectedTests);
        const updateSelectedPlatformsLazily = this._renderTriggerablePlatformsLazily.evaluate(this._selectedTests, this._triggerablePlatforms);
        if (updateSelectedPlatformsLazily)
            updateSelectedPlatformsLazily.evaluate(this._selectedPlatform);

        const [triggerable, error] = this._updateTriggerableLazily.evaluate(this._selectedTests, this._selectedPlatform);

        this._renderRepositoryPanesLazily.evaluate(triggerable, error, this._selectedPlatform, this._repositoryGroupByConfiguration, this._showComparison);

        this.renderReplace(this.content('baseline-testability'), this._buildTestabilityList(this._commitSetMap['Baseline'],
            'Baseline', this._invalidRevisionsByConfiguration['Baseline']));

        this.renderReplace(this.content('comparison-testability'), !this._showComparison ? null :
            this._buildTestabilityList(this._commitSetMap['Comparison'], 'Comparison', this._invalidRevisionsByConfiguration['Comparison']));
    }

    _renderTriggerableTests()
    {
        const enabledTriggerables = Triggerable.all().filter((triggerable) => !triggerable.isDisabled());

        const acceptedTests = new Set;
        for (const triggerable of enabledTriggerables) {
            for (const test of triggerable.acceptedTests())
                acceptedTests.add(test);
        }
        const tests = [...acceptedTests].sort((testA, testB) => {
            if (testA.fullName() == testB.fullName())
                return 0;
            return testA.fullName() < testB.fullName() ? -1 : 1;
        });
        return this._renderRadioButtonList(this.content('test-list'), 'test', tests, this.selectTests.bind(this), (test) => test.fullName());
    }

    _renderTriggerablePlatforms(selectedTests, triggerablePlatforms)
    {
        if (!selectedTests.length) {
            this.content('platform-pane').style.display = 'none';
            return null;
        }
        this.content('platform-pane').style.display = null;

        return this._renderRadioButtonList(this.content('platform-list'), 'platform', triggerablePlatforms, (selectedPlatforms) => {
            this.selectPlatform(selectedPlatforms.length ? selectedPlatforms[0] : null);
        });
    }

    _renderRadioButtonList(listContainer, name, objects, callback, labelForObject = (object) => object.label())
    {
        const listItems = [];
        let selectedListItems = [];
        const checkSelectedRadioButtons = (newSelectedListItems) => {
            selectedListItems.forEach((item) => {
                item.label.classList.remove('selected');
                item.radioButton.checked = false;
            });
            selectedListItems = newSelectedListItems;
            selectedListItems.forEach((item) => {
                item.label.classList.add('selected');
                item.radioButton.checked = true;
            });
        }

        const element = ComponentBase.createElement;
        this.renderReplace(listContainer, objects.map((object) => {
            const radioButton = element('input', {type: 'radio', name: name, onchange: () => {
                checkSelectedRadioButtons(listItems.filter((item) => item.radioButton.checked));
                callback(selectedListItems.map((item) => item.object));
                this.enqueueToRender();
            }});
            const label = element('label', [radioButton, labelForObject(object)]);
            listItems.push({radioButton, label, object});
            return element('li', label);
        }));

        return new LazilyEvaluatedFunction((...selectedObjects) => {
            const objects = new Set(selectedObjects);
            checkSelectedRadioButtons(listItems.filter((item) => objects.has(item.object)));
        });
    }

    _updateTriggerable(tests, platform)
    {
        let triggerable = null;
        let error = null;
        if (tests.length && platform) {
            triggerable = Triggerable.findByTestConfiguration(tests[0], platform);
            let matchingTests = new Set;
            let mismatchingTests = new Set;
            for (let test of tests) {
                if (Triggerable.findByTestConfiguration(test, platform) == triggerable)
                    matchingTests.add(test);
                else
                    mismatchingTests.add(test);
            }
            if (matchingTests.size < tests.length) {
                const matchingTestNames = [...matchingTests].map((test) => test.fullName()).sort().join('", "');
                const mismathingTestNames = [...mismatchingTests].map((test) => test.fullName()).sort().join('", "');
                error = `Tests "${matchingTestNames}" and "${mismathingTestNames}" cannot be scheduled
                    simultenosuly on "${platform.name()}". Please select one of them at a time.`;
            }
        }

        return [triggerable, error];
    }

    _updateRepositoryGroups(triggerable)
    {
        const repositoryGroups = triggerable ? TriggerableRepositoryGroup.sortByNamePreferringSmallerRepositories(triggerable.repositoryGroups()) : [];
        for (let name in this._repositoryGroupByConfiguration) {
            const currentGroup = this._repositoryGroupByConfiguration[name];
            let matchingGroup = null;
            if (currentGroup) {
                if (repositoryGroups.includes(currentGroup))
                    matchingGroup = currentGroup;
                else
                    matchingGroup = repositoryGroups.find((group) => group.name() == currentGroup.name());
            }
            if (!matchingGroup && repositoryGroups.length)
                matchingGroup = repositoryGroups[0];
            this._repositoryGroupByConfiguration[name] = matchingGroup;
        }
    }

    _updateCommitSetMap()
    {
        const newBaseline = this._computeCommitSet('Baseline');
        let newComparison = this._computeCommitSet('Comparison');
        if (newBaseline && newComparison && newBaseline.equals(newComparison))
            newComparison = null;

        const currentBaseline = this._commitSetMap['Baseline'];
        const currentComparison = this._commitSetMap['Comparison'];
        const areCommitSetsEqual = (commitSetA, commitSetB) => commitSetA == commitSetB || (commitSetA && commitSetB && commitSetA.equals(commitSetB));
        const sameBaselineConfig = areCommitSetsEqual(currentBaseline, newBaseline);
        const sameComparisionConfig = areCommitSetsEqual(currentComparison, newComparison);

        if (sameBaselineConfig && sameComparisionConfig)
            return;

        this._commitSetMap = {'Baseline': newBaseline, 'Comparison': newComparison};

        this.dispatchAction('testConfigChange');
        this.enqueueToRender();
    }

    _computeCommitSet(configurationName)
    {
        const repositoryGroup = this._repositoryGroupByConfiguration[configurationName];
        if (!repositoryGroup)
            return null;

        const fileUploader = this._customRootUploaders[configurationName];
        if (!fileUploader || fileUploader.hasFileToUpload())
            return null;

        const commitSet = new CustomCommitSet;
        for (let repository of repositoryGroup.repositories()) {
            let revision = this._specifiedRevisions[configurationName].get(repository);
            const commit = this._fetchedCommits[configurationName].get(repository);
            if (commit) {
                const commitLabel = commit.label();
                if (!revision || commit.revision().startsWith(revision) || commitLabel.startsWith(revision) || revision.startsWith(commitLabel))
                    revision = commit.revision();
            }
            if (!revision)
                return null;
            let patch = null;
            if (repositoryGroup.acceptsPatchForRepository(repository)) {
                const uploaderMap = this._patchUploaders[configurationName];
                const uploader = uploaderMap.get(repository);
                if (uploader) {
                    const files = uploader.uploadedFiles();
                    console.assert(files.length <= 1);
                    if (files.length)
                        patch = files[0];
                }
            }
            commitSet.setRevisionForRepository(repository, revision, patch);
        }

        for (let uploadedFile of fileUploader.uploadedFiles())
            commitSet.addCustomRoot(uploadedFile);

        return commitSet;
    }

    async _fetchCommitsForConfiguration(configurationName)
    {
        const commitSet = this._commitSetMap[configurationName];
        if (!commitSet)
            return;

        const specifiedRevisions = this._specifiedRevisions[configurationName];
        const fetchedCommits = this._fetchedCommits[configurationName];
        const invalidRevisionForRepository = this._invalidRevisionsByConfiguration[configurationName];

        await Promise.all(Array.from(commitSet.repositories()).map((repository) => {
            const revision = commitSet.revisionForRepository(repository);
            return this._resolveRevision(repository, revision, specifiedRevisions, invalidRevisionForRepository, fetchedCommits);
        }));

        const latestCommitSet = this._commitSetMap[configurationName];
        if (commitSet != latestCommitSet)
            return;
        this.enqueueToRender();
    }

    async _resolveRevision(repository, revision, specifiedRevisions, invalidRevisionForRepository, fetchedCommits)
    {
        const fetchedCommit = fetchedCommits.get(repository);
        const specifiedRevision = specifiedRevisions.get(repository);
        if (fetchedCommit && fetchedCommit.revision() == revision && (!specifiedRevision || specifiedRevision == revision))
            return;

        fetchedCommits.delete(repository);
        let commits = [];
        const revisionToFetch = specifiedRevision || revision;
        try {
            commits = await CommitLog.fetchForSingleRevision(repository, revisionToFetch, true);
        } catch (error) {
            console.assert(error == 'UnknownCommit' || error == 'AmbiguousRevisionPrefix');
            if (revisionToFetch != specifiedRevisions.get(repository))
                return;
            invalidRevisionForRepository.set(repository, `"${revisionToFetch}": ${error == 'UnknownCommit' ? 'Invalid revision' : 'Ambiguous revision prefix'}`);
            return;
        }
        console.assert(commits.length, 1);
        if (revisionToFetch != specifiedRevisions.get(repository))
            return;
        invalidRevisionForRepository.delete(repository);
        fetchedCommits.set(repository, commits[0]);
        if (revisionToFetch != commits[0].revision())
            this._updateCommitSetMap();
    }

    _renderRepositoryPanes(triggerable, error, platform, repositoryGroupByConfiguration, showComparison)
    {
        this.content('repository-configuration-error-pane').style.display = error ? null : 'none';
        this.content('error').textContent = error;

        this.content('baseline-configuration-pane').style.display = triggerable ? null : 'none';
        this.content('specify-comparison-pane').style.display = triggerable && !showComparison ? null : 'none';
        this.content('comparison-configuration-pane').style.display = triggerable && showComparison ? null : 'none';

        if (!triggerable)
            return;

        const visibleRepositoryGroups = triggerable.repositoryGroups().filter((group) => !group.isHidden());
        const repositoryGroups = TriggerableRepositoryGroup.sortByNamePreferringSmallerRepositories(visibleRepositoryGroups);

        const repositorySet = new Set;
        for (let group of repositoryGroups) {
            for (let repository of group.repositories())
                repositorySet.add(repository);
        }

        const repositories = Repository.sortByNamePreferringOnesWithURL([...repositorySet]);
        const requiredRepositories = repositories.filter((repository) => {
            return repositoryGroups.every((group) => group.repositories().includes(repository));
        });
        const alwaysAcceptsCustomRoots = repositoryGroups.every((group) => group.acceptsCustomRoots());

        this._renderBaselineRevisionTable(platform, repositoryGroups, requiredRepositories, repositoryGroupByConfiguration, alwaysAcceptsCustomRoots);

        if (showComparison)
            this._renderComparisonRevisionTable(platform, repositoryGroups, requiredRepositories, repositoryGroupByConfiguration, alwaysAcceptsCustomRoots);
    }

    _renderBaselineRevisionTable(platform, repositoryGroups, requiredRepositories, repositoryGroupByConfiguration, alwaysAcceptsCustomRoots)
    {
        let currentGroup = repositoryGroupByConfiguration['Baseline'];
        const optionalRepositoryList = this._optionalRepositoryList(currentGroup, requiredRepositories);
        this.renderReplace(this.content('baseline-revision-table'),
            this._buildRevisionTable('Baseline', repositoryGroups, currentGroup, platform, requiredRepositories, optionalRepositoryList, alwaysAcceptsCustomRoots));
    }

    _renderComparisonRevisionTable(platform, repositoryGroups, requiredRepositories, repositoryGroupByConfiguration, alwaysAcceptsCustomRoots)
    {
        let currentGroup = repositoryGroupByConfiguration['Comparison'];
        const optionalRepositoryList = this._optionalRepositoryList(currentGroup, requiredRepositories);
        this.renderReplace(this.content('comparison-revision-table'),
            this._buildRevisionTable('Comparison', repositoryGroups, currentGroup, platform, requiredRepositories, optionalRepositoryList, alwaysAcceptsCustomRoots));
    }

    _optionalRepositoryList(currentGroup, requiredRepositories)
    {
        if (!currentGroup)
            return [];
        return Repository.sortByNamePreferringOnesWithURL(currentGroup.repositories().filter((repository) => !requiredRepositories.includes(repository)));
    }

    _buildRevisionTable(configurationName, repositoryGroups, currentGroup, platform, requiredRepositories, optionalRepositoryList, alwaysAcceptsCustomRoots)
    {
        const element = ComponentBase.createElement;

        const customRootsTBody = element('tbody', [
            element('tr', [
                element('th', 'Roots'),
                element('td', this._customRootUploaders[configurationName]),
            ]),
        ]);

        return [
            element('tbody',
                requiredRepositories.map((repository) => {
                    return element('tr', [
                        element('th', repository.name()),
                        element('td', this._buildRevisionInput(configurationName, repository, platform))
                    ]);
                })),
            alwaysAcceptsCustomRoots ? customRootsTBody : [],
            element('tbody', [
                element('tr', {'class': 'group-row'},
                    element('td', {colspan: 2}, this._buildRepositoryGroupList(repositoryGroups, currentGroup, configurationName))),
            ]),
            !alwaysAcceptsCustomRoots && currentGroup && currentGroup.acceptsCustomRoots() ? customRootsTBody : [],
            element('tbody',
                optionalRepositoryList.map((repository) => {
                    let uploader = currentGroup.acceptsPatchForRepository(repository)
                        ? this._ensurePatchUploader(configurationName, repository) : null;

                    return element('tr',[
                        element('th', repository.name()),
                        element('td', [
                            this._buildRevisionInput(configurationName, repository, platform),
                            uploader || [],
                        ])
                    ]);
                })
            )];
    }

    _buildTestabilityList(commitSet, configurationName, invalidRevisionForRepository)
    {
        const element = ComponentBase.createElement;
        const entries = [];

        if (!commitSet || !commitSet.repositories().length)
            return [];

        for (const repository of commitSet.repositories()) {
            const commit = this._fetchedCommits[configurationName].get(repository);
            if (commit && commit.testability() && !invalidRevisionForRepository.has(repository))
                entries.push(element('li', `${commit.repository().name()} - "${commit.label()}": ${commit.testability()}`));
            if (invalidRevisionForRepository.has(repository))
                entries.push(element('li', `${repository.name()} - ${invalidRevisionForRepository.get(repository)}`));
        }

        return entries;
    }

    _buildRepositoryGroupList(repositoryGroups, currentGroup, configurationName)
    {
        const element = ComponentBase.createElement;
        return repositoryGroups.map((group) => {
            const input = element('input', {
                type: 'radio',
                name: 'repositoryGroup-for-' + configurationName.toLowerCase(),
                checked: currentGroup == group,
                onchange: () => this._selectRepositoryGroup(configurationName, group)
            });
            return [element('label', [input, group.description()])];
        });
    }

    _selectRepositoryGroup(configurationName, group)
    {
        const source = this._repositoryGroupByConfiguration;
        const clone = {};
        for (let key in source)
            clone[key] = source[key];
        clone[configurationName] = group;
        this._repositoryGroupByConfiguration = clone;
        this._updateCommitSetMap();
        this._fetchCommitsForConfiguration(configurationName);
        this.enqueueToRender();
    }

    _buildRevisionInput(configurationName, repository, platform)
    {
        const revision = this._specifiedRevisions[configurationName].get(repository) || '';
        const element = ComponentBase.createElement;
        let scheduledUpdate = null;
        const input = element('input', {value: revision, oninput: () => {
            unmodifiedInput = null;
            const revisionToFetch = input.value;
            this._specifiedRevisions[configurationName].set(repository, revisionToFetch);
            this._updateCommitSetMap();
            if (scheduledUpdate)
                clearTimeout(scheduledUpdate);
            scheduledUpdate = setTimeout(() => {
                if (revisionToFetch == input.value)
                    this._fetchCommitsForConfiguration(configurationName);
                scheduledUpdate = null;
            }, CustomAnalysisTaskConfigurator.commitFetchInterval);
        }});
        let unmodifiedInput = input;

        if (!revision) {
            CommitLog.fetchLatestCommitForPlatform(repository, platform).then((commit) => {
                if (commit && unmodifiedInput) {
                    unmodifiedInput.value = commit.revision();
                    this._fetchedCommits[configurationName].set(repository, commit);
                    this._updateCommitSetMap();
                }
            });
        }

        return input;
    }

    static htmlTemplate()
    {
        return `
            <section id="test-pane" class="pane">
                <h2>1. Select a Test</h2>
                <ul id="test-list" class="config-list"></ul>
            </section>
            <section id="platform-pane" class="pane">
                <h2>2. Select a Platform</h2>
                <ul id="platform-list" class="config-list"></ul>
            </section>
            <section id="repository-configuration-error-pane" class="pane">
                <h2>Incompatible tests</h2>
                <p id="error"></p>
            </section>
            <section id="baseline-configuration-pane" class="pane">
                <h2>3. Configure Baseline</h2>
                <table id="baseline-revision-table" class="revision-table"></table>
                <ul id="baseline-testability"></ul>
            </section>
            <section id="specify-comparison-pane" class="pane">
                <button id="specify-comparison-button">Configure to Compare</button>
            </section>
            <section id="comparison-configuration-pane" class="pane">
                <h2>4. Configure Comparison</h2>
                <table id="comparison-revision-table" class="revision-table"></table>
                <ul id="comparison-testability"></ul>
            </section>`;
    }

    static cssTemplate()
    {
        return `
            :host {
                display: flex !important;
                flex-direction: row !important;
            }
            .pane {
                margin-right: 1rem;
                padding: 0;
            }
            .pane h2 {
                padding: 0;
                margin: 0;
                margin-bottom: 0.5rem;
                font-size: 1.2rem;
                font-weight: inherit;
                text-align: center;
                white-space: nowrap;
            }

            .config-list {
                height: 20rem;
                overflow: scroll;
                display: block;
                margin: 0;
                padding: 0;
                list-style: none;
                font-size: inherit;
                font-weight: inherit;
                border: none;
                border-top: solid 1px #ddd;
                border-bottom: solid 1px #ddd;
                white-space: nowrap;
            }

            #platform-list:empty:before {
                content: "No matching platform";
                display: block;
                margin: 1rem 0.5rem;
                text-align: center;
            }

            .config-list label {
                display: block;
                padding: 0.1rem 0.2rem;
            }

            .config-list label:hover,
            .config-list a:hover {
                background: rgba(204, 153, 51, 0.1);
            }

            .config-list label.selected,
            .config-list a.selected {
                background: #eee;
            }

            .config-list a {
                display: block;
                padding: 0.1rem 0.2rem;
                text-decoration: none;
                color: inherit;
            }

            #repository-configuration-pane {
                position: relative;
            }

            #repository-configuration-pane > button  {
                margin-left: 19.5rem;
            }

            .revision-table {
                border: none;
                border-collapse: collapse;
                font-size: 1rem;
            }

            .revision-table thead {
                font-size: 1.2rem;
            }

            .revision-table tbody:empty {
                display: none;
            }

            .revision-table tbody td,
            .revision-table tbody th {
                border-top: solid 1px #ddd;
                padding-top: 0.5rem;
                padding-bottom: 0.5rem;
            }

            .revision-table td,
            .revision-table th {
                width: 15rem;
                height: 1.8rem;
                padding: 0 0.2rem;
                border: none;
                font-weight: inherit;
            }

            .revision-table thead th {
                text-align: center;
            }

            .revision-table th close-button {
                vertical-align: bottom;
            }

            .revision-table td:first-child,
            .revision-table th:first-child {
                width: 6rem;
            }

            .revision-table tr.group-row td {
                padding-left: 5rem;
            }

            label {
                white-space: nowrap;
                display: block;
            }

            input:not([type=radio]) {
                width: calc(100% - 0.6rem);
                padding: 0.1rem 0.2rem;
                font-size: 0.9rem;
                font-weight: inherit;
            }

            #specify-comparison-pane button {
                margin-top: 1.5rem;
                font-size: 1.1rem;
                font-weight: inherit;
            }

            #start-pane button {
                margin-top: 1.5rem;
                font-size: 1.2rem;
                font-weight: inherit;
            }

            #baseline-testability li,
            #comparison-testability li {
                color: #c33;
                width: 20rem;
            }
`;
    }
}

CustomAnalysisTaskConfigurator.commitFetchInterval = 100;

ComponentBase.defineElement('custom-analysis-task-configurator', CustomAnalysisTaskConfigurator);
