"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decompile = void 0;
const ton_core_1 = require("ton-core");
const loadOpcode_1 = require("../codepage/loadOpcode");
function decompile(args) {
    // Load cell
    let cell;
    if (Buffer.isBuffer(args.src)) {
        cell = ton_core_1.Cell.fromBoc(args.src)[0];
    }
    else {
        cell = args.src;
    }
    // Result collection
    let result = [];
    // Parse cell
    let sc = cell.beginParse();
    let scl = sc.remainingBits;
    let sco = 0;
    while (sc.remainingBits > 0) {
        // Load opcode
        const opcode = (0, loadOpcode_1.loadOpcode)(sc);
        // Update state
        let currentOffset = sco; // Persisted offset before reading opcode
        let currentLength = scl - sc.remainingBits; // Check difference in remaining bits to calculate opcode length
        scl -= currentLength;
        sco += currentLength;
        // Failed case
        if (!opcode.ok) {
            if (args.allowUnknown) {
                let fullCell = (0, ton_core_1.beginCell)();
                for (let bit of Array.from(opcode.read).map(a => a == '0' ? false : true)) {
                    fullCell.storeBit(bit);
                }
                fullCell.storeSlice(sc);
                result.push({
                    op: {
                        code: 'unknown',
                        data: fullCell.endCell()
                    },
                    offset: currentOffset,
                    length: currentLength
                });
                break;
            }
            else {
                throw Error('Unknown opcode: b' + opcode.read);
            }
        }
        // Push opcode to result
        result.push({
            op: opcode.read,
            offset: currentOffset,
            length: currentLength
        });
        // Implicit jump
        if (sc.remainingBits === 0 && sc.remainingRefs > 0) {
            sc = sc.loadRef().beginParse();
            scl = sc.remainingBits;
            sco = 0;
        }
    }
    return result;
}
exports.decompile = decompile;
