import { NgModule, Injectable, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { __awaiter, __generator } from 'tslib';
import '@iotize/tap-scripts/ext';
import { bufferToHexString, bufferToAsciiString } from '@iotize/common/byte-converter';
import { GlobalEventsService } from '@iotize/ionic';
import { GrammarHelper, ScriptRunner } from '@iotize/tap-scripts';
import { Subject } from 'rxjs';
import { share } from 'rxjs/operators';

/**
 * @fileoverview added by tsickle
 * Generated from: lib/tap-script.module.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
var TapScriptModule = /** @class */ (function () {
    function TapScriptModule() {
    }
    TapScriptModule.decorators = [
        { type: NgModule, args: [{
                    declarations: [],
                    imports: [
                        CommonModule
                    ]
                },] }
    ];
    return TapScriptModule;
}());

/**
 * @fileoverview added by tsickle
 * Generated from: lib/tap-script-runner.service.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function ScriptOutputType() { }
if (false) {
    /** @type {?} */
    ScriptOutputType.prototype.level;
    /** @type {?} */
    ScriptOutputType.prototype.message;
}
var TapScriptRunnerService = /** @class */ (function () {
    function TapScriptRunnerService(events) {
        var _this = this;
        this.events = events;
        this.scriptTypes = {
            NORMAL: 1,
            CONFIGURATION: 2
        };
        this._outputMessages = [];
        this._errors = new Subject();
        this.output = new Subject();
        /**
         * The ScriptRunner object is given options with what is done with values retrieved by the script
         * The output property defines the actions to perform on data retrieving.
         * The display property defines how to log informations given back by the scriptRunner.
         * @see {ScriptRunner}
         */
        this.scriptRunnerOptions = {
            output: (/**
             * @param {?=} response
             * @return {?}
             */
            function (response) {
                /**
                 * Waiting for ScriptRunner update, display tweak
                 * If response is 1 or 2 bytes or contains 0, displays it as an hex string
                 * else displays it as an ASCII string
                 */
                if (response) {
                    /** @type {?} */
                    var responseDisplayed = void 0;
                    /** @type {?} */
                    var responseBody = response.body();
                    if (responseBody.length <= 2 || responseBody.includes(0)) {
                        responseDisplayed = bufferToHexString(responseBody);
                    }
                    else {
                        responseDisplayed = bufferToAsciiString(responseBody);
                    }
                    _this.addOutput('info', "" + responseDisplayed);
                }
            }),
            display: (/**
             * @param {?} level
             * @param {?} content
             * @return {?}
             */
            function (level, content) {
                console.log("[" + level + "] : " + content);
                if (level == 'message') {
                    _this.addOutput('info', "" + content);
                    return;
                }
                _this.addOutput(level, content);
            })
        };
        this.scriptFile = {
            name: '',
            scriptString: ''
        };
        this.scriptType = this.scriptTypes.NORMAL;
    }
    Object.defineProperty(TapScriptRunnerService.prototype, "isRunning", {
        get: /**
         * @return {?}
         */
        function () {
            return this.scriptRunner !== undefined && this.scriptRunner.isRunning();
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(TapScriptRunnerService.prototype, "hasScript", {
        get: /**
         * @return {?}
         */
        function () {
            return this.scriptFile.scriptString !== '';
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Converts script content, read as a string, into a list of instructions
     * @param scriptString content of the loaded script file
     * @returns
     */
    /**
     * Converts script content, read as a string, into a list of instructions
     * @param {?} scriptString content of the loaded script file
     * @return {?}
     */
    TapScriptRunnerService.prototype.getProgInstructions = /**
     * Converts script content, read as a string, into a list of instructions
     * @param {?} scriptString content of the loaded script file
     * @return {?}
     */
    function (scriptString) {
        return GrammarHelper.toProgInstructions(scriptString);
    };
    /**
     * @param {?} instructions
     * @param {?} tap
     * @return {?}
     */
    TapScriptRunnerService.prototype.runScript = /**
     * @param {?} instructions
     * @param {?} tap
     * @return {?}
     */
    function (instructions, tap) {
        this._outputMessages = [];
        return this.executeScriptFromInstructions(tap, instructions);
    };
    /**
     * @return {?}
     */
    TapScriptRunnerService.prototype.stopScript = /**
     * @return {?}
     */
    function () {
        // TODO
    };
    Object.defineProperty(TapScriptRunnerService.prototype, "errors", {
        get: /**
         * @return {?}
         */
        function () {
            return this._errors;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Reads and executes the given instruction list.
     * @param instructions
     */
    /**
     * Reads and executes the given instruction list.
     * @param {?} tap
     * @param {?} instructions
     * @return {?}
     */
    TapScriptRunnerService.prototype.executeScriptFromInstructions = /**
     * Reads and executes the given instruction list.
     * @param {?} tap
     * @param {?} instructions
     * @return {?}
     */
    function (tap, instructions) {
        var _this = this;
        this._outputMessages = [];
        /** @type {?} */
        var checkErrorCount = 0;
        /** @type {?} */
        var scriptRunner = this.scriptRunner = new ScriptRunner(this.scriptRunnerOptions);
        scriptRunner.errorHandler = (/**
         * @param {?} error
         * @return {?}
         */
        function (error) {
            // this.addOutput('error', error.message);
            _this._errors.next(error);
            // console.error(error);
            if (/Check instruction/.test(error.message)) {
                checkErrorCount++;
            }
        });
        return scriptRunner.run(instructions, tap)
            .pipe(
        // rxTap({
        //   next: (event: ScriptRunnerEvent) => {
        //     console.warn(event);
        //     if (event.type == 'after') {
        //       if ('cmd' in event.instruction) {
        //         // this.addOutput('verbose', `Command ${event.instruction['cmd'].toString()}`);
        //       }
        //     }
        //   },
        //   complete: () => {
        //     console.log("Script execution: DONE");
        //     // this.addOutput('info', '\n');
        //     // this.addOutput('info', '--------Script execution: DONE--------');
        //     if (checkErrorCount > 0) {
        //       // this.addOutput('error', `Failed Check instructions: ${checkErrorCount}`);
        //     }
        //     // this.isRunning = false;
        //   },
        //   error: (error) => {
        //     console.error(error);
        //     // this.isRunning = false;
        //   }
        // }),
        share());
    };
    /**
     * @return {?}
     */
    TapScriptRunnerService.prototype.stop = /**
     * @return {?}
     */
    function () {
        if (this.scriptRunner) {
            this.scriptRunner.stop();
        }
    };
    /**
     * @param {?} level
     * @param {?} message
     * @return {?}
     */
    TapScriptRunnerService.prototype.addOutput = /**
     * @param {?} level
     * @param {?} message
     * @return {?}
     */
    function (level, message) {
        console.info('SCRIPT', level, message);
        this._outputMessages.push({
            level: level,
            message: message
        });
        this.output.next(this._outputMessages);
    };
    /**
     * Converts, reads and executes instructions from the raw content of a script file.
     * In the configuration routine, script execution is preceded by:
     * - Log as admin
     * - Factory reset
     * - Wait time
     * And succeeded with
     * - Wait time
     * - Configuration reload
     * - Wait time
     *
     * The configuration routine has succeeded if all these steps did.
     *
     * TODO remove as it's in library
     *
     * @param scriptString
     */
    /**
     * Converts, reads and executes instructions from the raw content of a script file.
     * In the configuration routine, script execution is preceded by:
     * - Log as admin
     * - Factory reset
     * - Wait time
     * And succeeded with
     * - Wait time
     * - Configuration reload
     * - Wait time
     *
     * The configuration routine has succeeded if all these steps did.
     *
     * TODO remove as it's in library
     *
     * @param {?} scriptString
     * @param {?} tap
     * @return {?}
     */
    TapScriptRunnerService.prototype.executeConfigurationScriptRoutine = /**
     * Converts, reads and executes instructions from the raw content of a script file.
     * In the configuration routine, script execution is preceded by:
     * - Log as admin
     * - Factory reset
     * - Wait time
     * And succeeded with
     * - Wait time
     * - Configuration reload
     * - Wait time
     *
     * The configuration routine has succeeded if all these steps did.
     *
     * TODO remove as it's in library
     *
     * @param {?} scriptString
     * @param {?} tap
     * @return {?}
     */
    function (scriptString, tap) {
        return __awaiter(this, void 0, void 0, function () {
            var waitingTime, instructions, factoryResetResponse, result, error_1, error_2, reloadResponse, error_3;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        waitingTime = 400;
                        instructions = this.getProgInstructions(scriptString);
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 4, , 5]);
                        console.log('@@@@@@@@@ Logging as admin @@@@@@@@@');
                        // TODO only if not already logged in as an admin
                        return [4 /*yield*/, tap.auth.login({
                                username: 'admin',
                                password: 'admin'
                            })];
                    case 2:
                        // TODO only if not already logged in as an admin
                        _a.sent();
                        console.log('@@@@@@@@@  factory reset @@@@@@@@@');
                        this.events.publish('configuration', 'factory reset');
                        factoryResetResponse = tap.service.device.factoryReset();
                        return [4 /*yield*/, factoryResetResponse];
                    case 3:
                        result = (_a.sent()).body();
                        console.log("factoryReset : " + result);
                        return [3 /*break*/, 5];
                    case 4:
                        error_1 = _a.sent();
                        console.error(error_1);
                        throw new Error('factory reset failed');
                    case 5:
                        this.events.publish('configuration', 'executing script');
                        console.log('@@@@@@@@@  Wait after factory reset, before script execution @@@@@@@@@');
                        return [4 /*yield*/, this.sleep(waitingTime)];
                    case 6:
                        _a.sent();
                        _a.label = 7;
                    case 7:
                        _a.trys.push([7, 9, , 10]);
                        return [4 /*yield*/, this.executeScriptFromInstructions(tap, instructions)];
                    case 8:
                        _a.sent();
                        return [3 /*break*/, 10];
                    case 9:
                        error_2 = _a.sent();
                        console.error(error_2);
                        throw new Error('Script execution failed');
                    case 10:
                        _a.trys.push([10, 13, , 14]);
                        console.log('@@@@@@@@@  Wait after script execution, before reloading config @@@@@@@@@');
                        //  5. wait 400ms
                        return [4 /*yield*/, this.sleep(waitingTime)];
                    case 11:
                        //  5. wait 400ms
                        _a.sent();
                        //  6. reload config. Custom call to post /1024//10 while reloadConfig method is not implemented
                        reloadResponse = tap.service.interface.reloadConfig();
                        console.log('Waiting for reloadResponse');
                        return [4 /*yield*/, reloadResponse];
                    case 12:
                        _a.sent();
                        return [3 /*break*/, 14];
                    case 13:
                        error_3 = _a.sent();
                        console.error(error_3);
                        throw new Error('Reloading config failed');
                    case 14: 
                    //  7. wait 400ms
                    return [4 /*yield*/, this.sleep(waitingTime)];
                    case 15:
                        //  7. wait 400ms
                        _a.sent();
                        console.log('@@@@@@@@@ configuration complete @@@@@@@@@');
                        this.events.publish('configuration', 'configuration completed');
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Executes currently loaded script, if no script is running, using the routine defined by the scriptType property
     */
    /**
     * Executes currently loaded script, if no script is running, using the routine defined by the scriptType property
     * @param {?} tap
     * @return {?}
     */
    TapScriptRunnerService.prototype.executeLoadedScript = /**
     * Executes currently loaded script, if no script is running, using the routine defined by the scriptType property
     * @param {?} tap
     * @return {?}
     */
    function (tap) {
        if (this.isRunning) {
            console.error('Another script is running');
            return;
        }
        if (this.scriptType === this.scriptTypes.CONFIGURATION) {
            return this.executeConfigurationScriptRoutine(this.scriptFile.scriptString, tap);
        }
        if (this.scriptType === this.scriptTypes.NORMAL) {
            return this.executeScriptFromInstructions(tap, this.getProgInstructions(this.scriptFile.scriptString));
        }
    };
    /**
     * Returns a promise that resolve after given time in milliseconds
     * @param milliseconds
     * @returns
     */
    /**
     * Returns a promise that resolve after given time in milliseconds
     * @param {?} milliseconds
     * @return {?}
     */
    TapScriptRunnerService.prototype.sleep = /**
     * Returns a promise that resolve after given time in milliseconds
     * @param {?} milliseconds
     * @return {?}
     */
    function (milliseconds) {
        return new Promise((/**
         * @param {?} resolve
         * @return {?}
         */
        function (resolve) {
            setTimeout((/**
             * @return {?}
             */
            function () { return resolve(); }), milliseconds);
        }));
    };
    TapScriptRunnerService.decorators = [
        { type: Injectable, args: [{
                    providedIn: 'root'
                },] }
    ];
    /** @nocollapse */
    TapScriptRunnerService.ctorParameters = function () { return [
        { type: GlobalEventsService }
    ]; };
    /** @nocollapse */ TapScriptRunnerService.ɵprov = ɵɵdefineInjectable({ factory: function TapScriptRunnerService_Factory() { return new TapScriptRunnerService(ɵɵinject(GlobalEventsService)); }, token: TapScriptRunnerService, providedIn: "root" });
    return TapScriptRunnerService;
}());
if (false) {
    /** @type {?} */
    TapScriptRunnerService.prototype.scriptTypes;
    /** @type {?} */
    TapScriptRunnerService.prototype.scriptRunner;
    /** @type {?} */
    TapScriptRunnerService.prototype._outputMessages;
    /** @type {?} */
    TapScriptRunnerService.prototype._errors;
    /** @type {?} */
    TapScriptRunnerService.prototype.output;
    /**
     * The ScriptRunner object is given options with what is done with values retrieved by the script
     * The output property defines the actions to perform on data retrieving.
     * The display property defines how to log informations given back by the scriptRunner.
     * @see {ScriptRunner}
     * @type {?}
     */
    TapScriptRunnerService.prototype.scriptRunnerOptions;
    /** @type {?} */
    TapScriptRunnerService.prototype.scriptFile;
    /** @type {?} */
    TapScriptRunnerService.prototype.scriptType;
    /** @type {?} */
    TapScriptRunnerService.prototype.events;
}

/**
 * @fileoverview added by tsickle
 * Generated from: lib/definitions.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
/**
 * @record
 */
function ScriptFile() { }
if (false) {
    /** @type {?} */
    ScriptFile.prototype.name;
    /** @type {?} */
    ScriptFile.prototype.scriptString;
}

/**
 * @fileoverview added by tsickle
 * Generated from: public_api.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

/**
 * @fileoverview added by tsickle
 * Generated from: iotize-ionic-scripts.ts
 * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */

export { TapScriptModule, TapScriptRunnerService };
//# sourceMappingURL=iotize-ionic-scripts.js.map
