"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments)).next());
    });
};
const path = require("path");
const temp = require("temp");
class LiveSyncProvider {
    constructor($androidLiveSyncServiceLocator, $iosLiveSyncServiceLocator, $platformService, $platformsData, $logger, $childProcess, $options) {
        this.$androidLiveSyncServiceLocator = $androidLiveSyncServiceLocator;
        this.$iosLiveSyncServiceLocator = $iosLiveSyncServiceLocator;
        this.$platformService = $platformService;
        this.$platformsData = $platformsData;
        this.$logger = $logger;
        this.$childProcess = $childProcess;
        this.$options = $options;
        this.deviceSpecificLiveSyncServicesCache = {};
    }
    get deviceSpecificLiveSyncServices() {
        return {
            android: (_device, $injector) => {
                if (!this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier]) {
                    this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier] = $injector.resolve(this.$androidLiveSyncServiceLocator.factory, { _device: _device });
                }
                return this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier];
            },
            ios: (_device, $injector) => {
                if (!this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier]) {
                    this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier] = $injector.resolve(this.$iosLiveSyncServiceLocator.factory, { _device: _device });
                }
                return this.deviceSpecificLiveSyncServicesCache[_device.deviceInfo.identifier];
            }
        };
    }
    buildForDevice(device, projectData) {
        return __awaiter(this, void 0, void 0, function* () {
            let buildConfig = {
                buildForDevice: !device.isEmulator,
                projectDir: this.$options.path,
                release: this.$options.release,
                teamId: this.$options.teamId,
                device: this.$options.device,
                provision: this.$options.provision,
            };
            yield this.$platformService.buildPlatform(device.deviceInfo.platform, buildConfig, projectData);
            let platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData);
            if (device.isEmulator) {
                return this.$platformService.getLatestApplicationPackageForEmulator(platformData, buildConfig).packageName;
            }
            return this.$platformService.getLatestApplicationPackageForDevice(platformData, buildConfig).packageName;
        });
    }
    preparePlatformForSync(platform, provision, projectData) {
        return __awaiter(this, void 0, void 0, function* () {
            const appFilesUpdaterOptions = { bundle: this.$options.bundle, release: this.$options.release };
            yield this.$platformService.preparePlatform(platform, appFilesUpdaterOptions, this.$options.platformTemplate, projectData, this.$options);
        });
    }
    canExecuteFastSync(filePath, projectData, platform) {
        let platformData = this.$platformsData.getPlatformData(platform, projectData);
        let fastSyncFileExtensions = LiveSyncProvider.FAST_SYNC_FILE_EXTENSIONS.concat(platformData.fastLivesyncFileExtensions);
        return _.includes(fastSyncFileExtensions, path.extname(filePath));
    }
    transferFiles(deviceAppData, localToDevicePaths, projectFilesPath, isFullSync) {
        return __awaiter(this, void 0, void 0, function* () {
            if (deviceAppData.platform.toLowerCase() === "android" || !deviceAppData.deviceSyncZipPath || !isFullSync) {
                yield deviceAppData.device.fileSystem.transferFiles(deviceAppData, localToDevicePaths);
            }
            else {
                temp.track();
                let tempZip = temp.path({ prefix: "sync", suffix: ".zip" });
                this.$logger.trace("Creating zip file: " + tempZip);
                if (this.$options.syncAllFiles) {
                    yield this.$childProcess.spawnFromEvent("zip", ["-r", "-0", tempZip, "app"], "close", { cwd: path.dirname(projectFilesPath) });
                }
                else {
                    this.$logger.info("Skipping node_modules folder! Use the syncAllFiles option to sync files from this folder.");
                    yield this.$childProcess.spawnFromEvent("zip", ["-r", "-0", tempZip, "app", "-x", "app/tns_modules/*"], "close", { cwd: path.dirname(projectFilesPath) });
                }
                deviceAppData.device.fileSystem.transferFiles(deviceAppData, [{
                        getLocalPath: () => tempZip,
                        getDevicePath: () => deviceAppData.deviceSyncZipPath,
                        getRelativeToProjectBasePath: () => "../sync.zip",
                        deviceProjectRootPath: yield deviceAppData.getDeviceProjectRootPath()
                    }]);
            }
        });
    }
}
LiveSyncProvider.FAST_SYNC_FILE_EXTENSIONS = [".css", ".xml"];
exports.LiveSyncProvider = LiveSyncProvider;
$injector.register("liveSyncProvider", LiveSyncProvider);
