"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WrapperFuncsVisitor = exports.WrapperVarsVisitor = void 0;
const ast_1 = require("@wapc/widl/ast");
const helpers_1 = require("./helpers");
const utils_1 = require("../utils");
class WrapperVarsVisitor extends ast_1.BaseVisitor {
    constructor(writer) {
        super(writer);
    }
    visitOperation(context) {
        if (!utils_1.shouldIncludeHandler(context)) {
            return;
        }
        if (context.config.handlerPreamble != true) {
            this.write(`#[cfg(feature = "guest")]
lazy_static! {\n`);
            context.config.handlerPreamble = true;
        }
        const operation = context.operation;
        this.write(`static ref ${helpers_1.functionName(operation.name.value).toUpperCase()}: RwLock<Option<fn(`);
        operation.arguments.forEach((arg, i) => {
            if (i > 0) {
                this.write(`, `);
            }
            this.write(helpers_1.expandType(arg.type, undefined, true, helpers_1.isReference(arg.annotations)));
        });
        this.write(`) -> HandlerResult<`);
        if (!helpers_1.isVoid(operation.type)) {
            this.write(`${helpers_1.expandType(operation.type, undefined, true, helpers_1.isReference(operation.annotations))}`);
        }
        else {
            this.write(`()`);
        }
        this.write(`>>> = RwLock::new(None);\n`);
    }
    visitAllOperationsAfter(context) {
        if (context.config.handlerPreamble == true) {
            this.write(`}\n\n`);
        }
        super.triggerAllOperationsAfter(context);
    }
}
exports.WrapperVarsVisitor = WrapperVarsVisitor;
class WrapperFuncsVisitor extends ast_1.BaseVisitor {
    constructor(writer) {
        super(writer);
    }
    visitOperation(context) {
        if (!utils_1.shouldIncludeHandler(context)) {
            return;
        }
        const operation = context.operation;
        this.write(`#[cfg(feature = "guest")]
fn ${helpers_1.functionName(operation.name.value)}_wrapper(input_payload: &[u8]) -> CallResult {\n`);
        if (operation.isUnary()) {
            this.write(`let input = deserialize::<${helpers_1.expandType(operation.unaryOp().type, undefined, false, helpers_1.isReference(operation.annotations))}>(input_payload)?;
      let lock = ${helpers_1.functionName(operation.name.value).toUpperCase()}.read().unwrap().unwrap();
      let result = lock(input)?;\n`);
        }
        else {
            this.write(`let input = deserialize::<${helpers_1.capitalize(operation.name.value)}Args>(input_payload)?;
      let lock = ${helpers_1.functionName(operation.name.value).toUpperCase()}.read().unwrap().unwrap();\n`);
            this.write(`let result = lock(${helpers_1.varAccessArg("input", operation.arguments)})?;\n`);
        }
        this.write(`Ok(serialize(result)?)\n`);
        this.write(`}\n\n`);
    }
    visitWrapperBeforeReturn(context) {
        this.triggerCallbacks(context, "WrapperBeforeReturn");
    }
}
exports.WrapperFuncsVisitor = WrapperFuncsVisitor;
//# sourceMappingURL=wrappers_visitor.js.map