'use strict';

let assert = require('assert');

require('./v3-models.js');

let BuildbotSyncer = require('./buildbot-syncer').BuildbotSyncer;

class BuildbotTriggerable {
    constructor(config, remote, buildbotRemote, slaveInfo, logger)
    {
        this._name = config.triggerableName;
        assert(typeof(this._name) == 'string', 'triggerableName must be specified');

        this._lookbackCount = config.lookbackCount;
        assert(typeof(this._lookbackCount) == 'number' && this._lookbackCount > 0, 'lookbackCount must be a number greater than 0');

        this._remote = remote;
        this._config = config;
        this._buildbotRemote = buildbotRemote;

        this._slaveInfo = slaveInfo;
        assert(typeof(slaveInfo.name) == 'string', 'slave name must be specified');
        assert(typeof(slaveInfo.password) == 'string', 'slave password must be specified');

        this._syncers = null;
        this._logger = logger || {log: () => { }, error: () => { }};
    }

    getBuilderNameToIDMap()
    {
        return this._buildbotRemote.getJSON("/api/v2/builders").then((content) => {
            assert(content.builders instanceof Array);

            const builderNameToIDMap = {};
            for (const builder of content.builders)
                builderNameToIDMap[builder.name] = builder.builderid;

            return builderNameToIDMap;
        });
    }

    initSyncers()
    {
        return this.getBuilderNameToIDMap().then((builderNameToIDMap) => {
            this._syncers = BuildbotSyncer._loadConfig(this._buildbotRemote, this._config, builderNameToIDMap);
        });
    }

    name() { return this._name; }

    updateTriggerable()
    {
        const map = new Map;
        let repositoryGroups = [];
        for (const syncer of this._syncers) {
            for (const config of syncer.testConfigurations()) {
                const entry = {test: config.test.id(), platform: config.platform.id()};
                map.set(entry.test + '-' + entry.platform, entry);
            }
            // FIXME: Move BuildbotSyncer._loadConfig here and store repository groups directly.
            repositoryGroups = syncer.repositoryGroups();
        }
        return this._remote.postJSONWithStatus(`/api/update-triggerable/`, {
            'slaveName': this._slaveInfo.name,
            'slavePassword': this._slaveInfo.password,
            'triggerable': this._name,
            'configurations': Array.from(map.values()),
            'repositoryGroups': Object.keys(repositoryGroups).map((groupName) => {
                const group = repositoryGroups[groupName];
                return {
                    name: groupName,
                    description: group.description,
                    acceptsRoots: group.acceptsRoots,
                    repositories: group.repositoryList,
                };
            })});
    }

    syncOnce()
    {
        let syncerList = this._syncers;
        let buildReqeustsByGroup = new Map;

        this._logger.log(`Fetching build requests for ${this._name}...`);
        let validRequests;
        return BuildRequest.fetchForTriggerable(this._name).then((buildRequests) => {
            validRequests = this._validateRequests(buildRequests);
            buildReqeustsByGroup = BuildbotTriggerable._testGroupMapForBuildRequests(buildRequests);
            return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
        }).then((updates) => {
            this._logger.log('Scheduling builds');
            const promistList = [];
            const testGroupList = Array.from(buildReqeustsByGroup.values()).sort(function (a, b) { return a.groupOrder - b.groupOrder; });
            for (const group of testGroupList) {
                const nextRequest = this._nextRequestInGroup(group, updates);
                if (!validRequests.has(nextRequest))
                    continue;
                const promise = this._scheduleRequestIfSlaveIsAvailable(nextRequest, group.requests,
                    nextRequest.isBuild() ? group.buildSyncer : group.testSyncer,
                    nextRequest.isBuild() ? group.buildSlaveName : group.testSlaveName);
                if (promise)
                    promistList.push(promise);
            }
            return Promise.all(promistList);
        }).then(() => {
            // Pull all buildbots for the second time since the previous step may have scheduled more builds.
            return this._pullBuildbotOnAllSyncers(buildReqeustsByGroup);
        }).then((updates) => {
            // FIXME: Add a new API that just updates the requests.
            return this._remote.postJSONWithStatus(`/api/build-requests/${this._name}`, {
                'slaveName': this._slaveInfo.name,
                'slavePassword': this._slaveInfo.password,
                'buildRequestUpdates': updates});
        });
    }

    _validateRequests(buildRequests)
    {
        const testPlatformPairs = {};
        const validatedRequests = new Set;
        for (let request of buildRequests) {
            if (!this._syncers.some((syncer) => syncer.matchesConfiguration(request))) {
                const key = request.platform().id + '-' + (request.isBuild() ? 'build' : request.test().id());
                const kind = request.isBuild() ? 'Building' : `"${request.test().fullName()}"`;
                if (!(key in testPlatformPairs))
                    this._logger.error(`Build request ${request.id()} has no matching configuration: ${kind} on "${request.platform().name()}".`);
                testPlatformPairs[key] = true;
                continue;
            }
            const triggerable = request.triggerable();
            if (!triggerable) {
                this._logger.error(`Build request ${request.id()} does not specify a valid triggerable`);
                continue;
            }
            assert(triggerable instanceof Triggerable, 'Must specify a valid triggerable');
            assert.equal(triggerable.name(), this._name, 'Must specify the triggerable of this syncer');
            const repositoryGroup = request.repositoryGroup();
            if (!repositoryGroup) {
                this._logger.error(`Build request ${request.id()} does not specify a repository group. Such a build request is no longer supported.`);
                continue;
            }
            const acceptedGroups = triggerable.repositoryGroups();
            if (!acceptedGroups.includes(repositoryGroup)) {
                const acceptedNames = acceptedGroups.map((group) => group.name()).join(', ');
                this._logger.error(`Build request ${request.id()} specifies ${repositoryGroup.name()} but triggerable ${this._name} only accepts ${acceptedNames}`);
                continue;
            }
            validatedRequests.add(request);
        }

        return validatedRequests;
    }

    _pullBuildbotOnAllSyncers(buildReqeustsByGroup)
    {
        let updates = {};
        let associatedRequests = new Set;
        return Promise.all(this._syncers.map((syncer) => {
            return syncer.pullBuildbot(this._lookbackCount).then((entryList) => {
                for (const entry of entryList) {
                    const request = BuildRequest.findById(entry.buildRequestId());
                    if (!request)
                        continue;
                    associatedRequests.add(request);

                    const info = buildReqeustsByGroup.get(request.testGroupId());
                    if (request.isBuild()) {
                        assert(!info.buildSyncer || info.buildSyncer == syncer);
                        if (entry.slaveName()) {
                            assert(!info.buildSlaveName || info.buildSlaveName == entry.slaveName());
                            info.buildSlaveName = entry.slaveName();
                        }
                        info.buildSyncer = syncer;
                    } else {
                        assert(!info.testSyncer || info.testSyncer == syncer);
                        if (entry.slaveName()) {
                            assert(!info.testSlaveName || info.testSlaveName == entry.slaveName());
                            info.testSlaveName = entry.slaveName();
                        }
                        info.testSyncer = syncer;
                    }

                    const newStatus = entry.buildRequestStatusIfUpdateIsNeeded(request);
                    if (newStatus) {
                        this._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to ${newStatus}`);
                        updates[entry.buildRequestId()] = {status: newStatus, url: entry.url(), statusDescription: entry.statusDescription()};
                    } else if (!request.statusUrl() || request.statusDescription() != entry.statusDescription()) {
                        this._logger.log(`Updating build request ${request.id()} status URL to ${entry.url()} and status detail from ${request.statusDescription()} to ${entry.statusDescription()}`);
                        updates[entry.buildRequestId()] = {status: request.status(), url: entry.url(), statusDescription: entry.statusDescription()};
                    }
                }
            });
        })).then(() => {
            for (const request of BuildRequest.all()) {
                if (request.hasStarted() && !request.hasFinished() && !associatedRequests.has(request)) {
                    this._logger.log(`Updating the status of build request ${request.id()} from ${request.status()} to failedIfNotCompleted`);
                    assert(!(request.id() in updates));
                    updates[request.id()] = {status: 'failedIfNotCompleted'};
                }
            }
        }).then(() => updates);
    }

    _nextRequestInGroup(groupInfo, pendingUpdates)
    {
        for (const request of groupInfo.requests) {
            if (request.isScheduled() || (request.id() in pendingUpdates && pendingUpdates[request.id()]['status'] == 'scheduled'))
                return null;
            if (request.isPending() && !(request.id() in pendingUpdates))
                return request;
            if (request.isBuild() && !request.hasCompleted())
                return null; // A build request is still pending, scheduled, running, or failed.
        }
        return null;
    }

    _scheduleRequestIfSlaveIsAvailable(nextRequest, requestsInGroup, syncer, slaveName)
    {
        if (!nextRequest)
            return null;

        const isFirstRequest = nextRequest == requestsInGroup[0] || !nextRequest.order();
        if (!isFirstRequest) {
            if (syncer)
                return this._scheduleRequestWithLog(syncer, nextRequest, requestsInGroup, slaveName);
            this._logger.error(`Could not identify the syncer for ${nextRequest.id()}.`);
        }

        // Pick a new syncer for the first test.
        for (const syncer of this._syncers) {
            const promise = this._scheduleRequestWithLog(syncer, nextRequest, requestsInGroup, null);
            if (promise)
                return promise;
        }
        return null;
    }

    _scheduleRequestWithLog(syncer, request, requestsInGroup, slaveName)
    {
        const promise = syncer.scheduleRequestInGroupIfAvailable(request, requestsInGroup, slaveName);
        if (!promise)
            return promise;
        this._logger.log(`Scheduling build request ${request.id()}${slaveName ? ' on ' + slaveName : ''} in ${syncer.builderName()}`);
        return promise;
    }

    static _testGroupMapForBuildRequests(buildRequests)
    {
        const map = new Map;
        let groupOrder = 0;
        for (let request of buildRequests) {
            let groupId = request.testGroupId();
            if (!map.has(groupId)) // Don't use real TestGroup objects to avoid executing postgres query in the server
                map.set(groupId, {id: groupId, groupOrder: groupOrder++, requests: [request], buildSyncer: null, testSyncer: null, slaveName: null});
            else
                map.get(groupId).requests.push(request);
        }
        return map;
    }
}

if (typeof module != 'undefined')
    module.exports.BuildbotTriggerable = BuildbotTriggerable;
