"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HmrStatusService = void 0;
const decorators_1 = require("../common/decorators");
const constants_1 = require("../common/constants");
const yok_1 = require("../common/yok");
class HmrStatusService {
    constructor($logParserService, $devicePlatformsConstants, $logger) {
        this.$logParserService = $logParserService;
        this.$devicePlatformsConstants = $devicePlatformsConstants;
        this.$logger = $logger;
        this.hashOperationStatuses = {};
        this.intervals = {};
    }
    getHmrStatus(deviceId, operationHash) {
        return new Promise((resolve, reject) => {
            const key = `${deviceId}${operationHash}`;
            let retryCount = 40;
            this.intervals[key] = setInterval(() => {
                const status = this.getStatusByKey(key);
                if (status || retryCount === 0) {
                    clearInterval(this.intervals[key]);
                    this.intervals[key] = null;
                    resolve(status);
                }
                else {
                    retryCount--;
                }
            }, 250);
        });
    }
    watchHmrStatus(deviceId, operationHash) {
        this.setData(deviceId, operationHash);
    }
    attachToHmrStatusEvent() {
        this.$logParserService.addParseRule({
            regex: HmrStatusService.HMR_STATUS_LOG_REGEX,
            handler: this.handleHmrStatusFound.bind(this),
            name: "hmrStatus",
        });
        this.$logParserService.addParseRule({
            regex: constants_1.IOS_APP_CRASH_LOG_REG_EXP,
            handler: this.handleAppCrash.bind(this),
            name: "appCrashHmr",
            platform: this.$devicePlatformsConstants.iOS.toLowerCase(),
        });
        this.$logParserService.addParseRule({
            regex: constants_1.FAIL_LIVESYNC_LOG_REGEX,
            handler: this.handleAppCrash.bind(this),
            name: "failedLiveSync",
            platform: this.$devicePlatformsConstants.iOS.toLowerCase(),
        });
        const statusStringMap = {
            success: constants_1.HmrConstants.HMR_SUCCESS_STATUS,
            failure: constants_1.HmrConstants.HMR_ERROR_STATUS,
        };
        this.$logParserService.addParseRule({
            regex: /\[HMR]\[(.+)]\s*(\w+)\s*\|/,
            handler: (matches, deviceId) => {
                const [hash, status] = matches.slice(1);
                const mappedStatus = statusStringMap[status.trim()];
                if (mappedStatus) {
                    this.setData(deviceId, hash, statusStringMap[status]);
                }
            },
            name: "hmr-status",
        });
    }
    handleAppCrash(matches, deviceId) {
        for (const operationId in this.hashOperationStatuses) {
            const operation = this.hashOperationStatuses[operationId];
            if (operationId.startsWith(deviceId) && !operation.status) {
                operation.status = constants_1.HmrConstants.HMR_ERROR_STATUS;
            }
        }
    }
    handleHmrStatusFound(matches, deviceId) {
        const message = matches[1].trim();
        const hash = matches[2];
        let status;
        switch (message) {
            case HmrStatusService.SUCCESS_MESSAGE: {
                status = constants_1.HmrConstants.HMR_SUCCESS_STATUS;
                break;
            }
            case HmrStatusService.FAILED_MESSAGE: {
                status = constants_1.HmrConstants.HMR_ERROR_STATUS;
                break;
            }
            default: {
                status = null;
                break;
            }
        }
        this.$logger.trace("Found hmr status.", { status, hash });
        if (status) {
            this.setData(deviceId, hash, status);
        }
    }
    getStatusByKey(key) {
        if (this.hashOperationStatuses[key]) {
            return this.hashOperationStatuses[key].status;
        }
        return null;
    }
    setData(deviceId, operationHash, status) {
        const key = `${deviceId}${operationHash}`;
        if (!this.hashOperationStatuses[key]) {
            this.hashOperationStatuses[key] = {};
        }
        this.hashOperationStatuses[key].status = status;
    }
}
HmrStatusService.HMR_STATUS_LOG_REGEX = /([a-z A-Z]*) hmr hash ([a-z0-9]*)\./;
HmrStatusService.STARTED_MESSAGE = "Checking for updates to the bundle with";
HmrStatusService.SUCCESS_MESSAGE = "Successfully applied update with";
HmrStatusService.FAILED_MESSAGE = "Cannot apply update with";
__decorate([
    (0, decorators_1.cache)()
], HmrStatusService.prototype, "attachToHmrStatusEvent", null);
exports.HmrStatusService = HmrStatusService;
yok_1.injector.register("hmrStatusService", HmrStatusService);
