
import { __decorate, __param } from '../../../../../../external/tslib/tslib.es6.js';
import { Emitter } from '../../../base/common/event.js';
import { Disposable } from '../../../base/common/lifecycle.js';
import { PlatformToString, Platform, isSafari, isChrome, isEdge, isFirefox, isAndroid, isWeb, platform } from '../../../base/common/platform.js';
import { escapeRegExpCharacters } from '../../../base/common/strings.js';
import { localize } from '../../../nls.js';
import { IEnvironmentService } from '../../environment/common/environment.service.js';
import { IFileService } from '../../files/common/files.service.js';
import { IProductService } from '../../product/common/productService.service.js';
import { getServiceMachineId } from '../../externalServices/common/serviceMachineId.js';
import { StorageScope, StorageTarget } from '../../storage/common/storage.js';
import { IStorageService } from '../../storage/common/storage.service.js';
import { IUserDataSyncStoreService, IUserDataSyncLogService } from './userDataSync.service.js';

var UserDataSyncMachinesService_1;
const currentMachineNameKey = "sync.currentMachineName";
const Safari = "Safari";
const Chrome = "Chrome";
const Edge = "Edge";
const Firefox = "Firefox";
const Android = "Android";
function isWebPlatform(platform) {
    switch (platform) {
    case Safari:
    case Chrome:
    case Edge:
    case Firefox:
    case Android:
    case PlatformToString(Platform.Web):
        return true;
    }
    return false;
}
function getPlatformName() {
    if (isSafari) {
        return Safari;
    }
    if (isChrome) {
        return Chrome;
    }
    if (isEdge) {
        return Edge;
    }
    if (isFirefox) {
        return Firefox;
    }
    if (isAndroid) {
        return Android;
    }
    return PlatformToString(isWeb ? Platform.Web : platform);
}
let UserDataSyncMachinesService = class UserDataSyncMachinesService extends Disposable {
    static {
        UserDataSyncMachinesService_1 = this;
    }
    static {
        this.VERSION = 1;
    }
    static {
        this.RESOURCE = "machines";
    }
    constructor(
        environmentService,
        fileService,
        storageService,
        userDataSyncStoreService,
        logService,
        productService
    ) {
        super();
        this.storageService = storageService;
        this.userDataSyncStoreService = userDataSyncStoreService;
        this.logService = logService;
        this.productService = productService;
        this._onDidChange = this._register(( new Emitter()));
        this.onDidChange = this._onDidChange.event;
        this.userData = null;
        this.currentMachineIdPromise = getServiceMachineId(environmentService, fileService, storageService);
    }
    async getMachines(manifest) {
        const currentMachineId = await this.currentMachineIdPromise;
        const machineData = await this.readMachinesData(manifest);
        return ( machineData.machines.map(machine => ({
            ...machine,
            ...{
                isCurrent: machine.id === currentMachineId
            }
        })));
    }
    async addCurrentMachine(manifest) {
        const currentMachineId = await this.currentMachineIdPromise;
        const machineData = await this.readMachinesData(manifest);
        if (!( machineData.machines.some((
            {
                id
            }
        ) => id === currentMachineId))) {
            machineData.machines.push({
                id: currentMachineId,
                name: this.computeCurrentMachineName(machineData.machines),
                platform: getPlatformName()
            });
            await this.writeMachinesData(machineData);
        }
    }
    async removeCurrentMachine(manifest) {
        const currentMachineId = await this.currentMachineIdPromise;
        const machineData = await this.readMachinesData(manifest);
        const updatedMachines = machineData.machines.filter((
            {
                id
            }
        ) => id !== currentMachineId);
        if (updatedMachines.length !== machineData.machines.length) {
            machineData.machines = updatedMachines;
            await this.writeMachinesData(machineData);
        }
    }
    async renameMachine(machineId, name, manifest) {
        const machineData = await this.readMachinesData(manifest);
        const machine = machineData.machines.find((
            {
                id
            }
        ) => id === machineId);
        if (machine) {
            machine.name = name;
            await this.writeMachinesData(machineData);
            const currentMachineId = await this.currentMachineIdPromise;
            if (machineId === currentMachineId) {
                this.storageService.store(
                    currentMachineNameKey,
                    name,
                    StorageScope.APPLICATION,
                    StorageTarget.MACHINE
                );
            }
        }
    }
    async setEnablements(enablements) {
        const machineData = await this.readMachinesData();
        for (const [machineId, enabled] of enablements) {
            const machine = machineData.machines.find(machine => machine.id === machineId);
            if (machine) {
                machine.disabled = enabled ? undefined : true;
            }
        }
        await this.writeMachinesData(machineData);
    }
    computeCurrentMachineName(machines) {
        const previousName = this.storageService.get(currentMachineNameKey, StorageScope.APPLICATION);
        if (previousName) {
            if (!( machines.some(machine => machine.name === previousName))) {
                return previousName;
            }
            this.storageService.remove(currentMachineNameKey, StorageScope.APPLICATION);
        }
        const namePrefix = `${this.productService.embedderIdentifier ? `${this.productService.embedderIdentifier} - ` : ""}${getPlatformName()} (${this.productService.nameShort})`;
        const nameRegEx = ( new RegExp(`${escapeRegExpCharacters(namePrefix)}\\s#(\\d+)`));
        let nameIndex = 0;
        for (const machine of machines) {
            const matches = nameRegEx.exec(machine.name);
            const index = matches ? parseInt(matches[1]) : 0;
            nameIndex = index > nameIndex ? index : nameIndex;
        }
        return `${namePrefix} #${nameIndex + 1}`;
    }
    async readMachinesData(manifest) {
        this.userData = await this.readUserData(manifest);
        const machinesData = this.parse(this.userData);
        if (machinesData.version !== UserDataSyncMachinesService_1.VERSION) {
            throw ( new Error(( localize(
                2525,
                "Cannot read machines data as the current version is incompatible. Please update {0} and try again.",
                this.productService.nameLong
            ))));
        }
        return machinesData;
    }
    async writeMachinesData(machinesData) {
        const content = JSON.stringify(machinesData);
        const ref = await this.userDataSyncStoreService.writeResource(
            UserDataSyncMachinesService_1.RESOURCE,
            content,
            this.userData?.ref || null
        );
        this.userData = {
            ref,
            content
        };
        this._onDidChange.fire();
    }
    async readUserData(manifest) {
        if (this.userData) {
            const latestRef = manifest && manifest.latest ? manifest.latest[UserDataSyncMachinesService_1.RESOURCE] : undefined;
            if (this.userData.ref === latestRef) {
                return this.userData;
            }
            if (latestRef === undefined && this.userData.content === null) {
                return this.userData;
            }
        }
        return this.userDataSyncStoreService.readResource(UserDataSyncMachinesService_1.RESOURCE, this.userData);
    }
    parse(userData) {
        if (userData.content !== null) {
            try {
                return JSON.parse(userData.content);
            } catch (e) {
                this.logService.error(e);
            }
        }
        return {
            version: UserDataSyncMachinesService_1.VERSION,
            machines: []
        };
    }
};
UserDataSyncMachinesService = UserDataSyncMachinesService_1 = ( __decorate([( __param(0, IEnvironmentService)), ( __param(1, IFileService)), ( __param(2, IStorageService)), ( __param(3, IUserDataSyncStoreService)), ( __param(4, IUserDataSyncLogService)), ( __param(5, IProductService))], UserDataSyncMachinesService));

export { UserDataSyncMachinesService, isWebPlatform };
