"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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const nativescript_preview_sdk_1 = require("nativescript-preview-sdk");
const preview_app_constants_1 = require("./preview-app-constants");
const events_1 = require("events");
const pako = require("pako");
class PreviewSdkService extends events_1.EventEmitter {
    constructor($config, $httpClient, $logger, $previewDevicesService, $previewAppLogProvider, $projectDataService) {
        super();
        this.$config = $config;
        this.$httpClient = $httpClient;
        this.$logger = $logger;
        this.$previewDevicesService = $previewDevicesService;
        this.$previewAppLogProvider = $previewAppLogProvider;
        this.$projectDataService = $projectDataService;
        this.messagingService = null;
        this.instanceId = null;
    }
    getQrCodeUrl(options) {
        const { projectDir, useHotModuleReload } = options;
        const projectData = this.$projectDataService.getProjectData(projectDir);
        const schema = projectData.previewAppSchema || "nsplay";
        const publishKey = preview_app_constants_1.PubnubKeys.PUBLISH_KEY;
        const subscribeKey = preview_app_constants_1.PubnubKeys.SUBSCRIBE_KEY;
        const hmrValue = useHotModuleReload ? "1" : "0";
        const result = `${schema}://boot?instanceId=${this.instanceId}&pKey=${publishKey}&sKey=${subscribeKey}&template=play-ng&hmr=${hmrValue}`;
        return result;
    }
    initialize(getInitialFiles) {
        return __awaiter(this, void 0, void 0, function* () {
            const initConfig = this.getInitConfig(getInitialFiles);
            this.messagingService = new nativescript_preview_sdk_1.MessagingService();
            this.instanceId = yield this.messagingService.initialize(initConfig);
        });
    }
    applyChanges(filesPayload) {
        return new Promise((resolve, reject) => {
            this.messagingService.applyChanges(this.instanceId, filesPayload, err => {
                if (err) {
                    reject(err);
                }
                else {
                    resolve();
                }
            });
        });
    }
    stop() {
        this.messagingService.stop();
    }
    getInitConfig(getInitialFiles) {
        return {
            pubnubPublishKey: preview_app_constants_1.PubnubKeys.PUBLISH_KEY,
            pubnubSubscribeKey: preview_app_constants_1.PubnubKeys.SUBSCRIBE_KEY,
            msvKey: "cli",
            msvEnv: this.$config.PREVIEW_APP_ENVIRONMENT,
            showLoadingPage: false,
            callbacks: this.getCallbacks(),
            getInitialFiles
        };
    }
    getCallbacks() {
        return {
            onLogSdkMessage: (log) => {
                this.$logger.trace("Received onLogSdkMessage message: ", log);
            },
            onLogMessage: (log, deviceName, deviceId) => {
                this.$previewAppLogProvider.logData(log, deviceName, deviceId);
            },
            onRestartMessage: () => {
                this.$logger.trace("Received onRestartMessage event.");
            },
            onUncaughtErrorMessage: () => {
                this.$logger.warn("The Preview app has terminated unexpectedly. Please run it again to get a detailed crash report.");
            },
            onConnectedDevicesChange: (connectedDevices) => ({}),
            onDeviceConnectedMessage: (deviceConnectedMessage) => ({}),
            onDeviceConnected: (device) => ({}),
            onDevicesPresence: (devices) => this.$previewDevicesService.updateConnectedDevices(devices),
            onSendingChange: (sending) => ({}),
            onBiggerFilesUpload: (filesContent, callback) => __awaiter(this, void 0, void 0, function* () {
                const gzippedContent = Buffer.from(pako.gzip(filesContent));
                const byteLength = filesContent.length;
                if (byteLength > PreviewSdkService.MAX_FILES_UPLOAD_BYTE_LENGTH) {
                    this.$logger.warn("The files to upload exceed the maximum allowed size of 15MB. Your app might not work as expected.");
                }
                const playgroundUploadResponse = yield this.$httpClient.httpRequest({
                    url: this.$config.UPLOAD_PLAYGROUND_FILES_ENDPOINT,
                    method: "POST",
                    body: gzippedContent,
                    headers: {
                        "Content-Encoding": "gzip",
                        "Content-Type": "text/plain"
                    }
                });
                const responseBody = JSON.parse(playgroundUploadResponse.body);
                const location = responseBody && responseBody.location;
                callback(location, playgroundUploadResponse.error);
            })
        };
    }
}
PreviewSdkService.MAX_FILES_UPLOAD_BYTE_LENGTH = 15 * 1024 * 1024;
exports.PreviewSdkService = PreviewSdkService;
$injector.register("previewSdkService", PreviewSdkService);
