export var StackItemType;
(function (StackItemType) {
    StackItemType[StackItemType["Any"] = 0] = "Any";
    StackItemType[StackItemType["Pointer"] = 16] = "Pointer";
    StackItemType[StackItemType["Boolean"] = 32] = "Boolean";
    StackItemType[StackItemType["Integer"] = 33] = "Integer";
    StackItemType[StackItemType["ByteString"] = 40] = "ByteString";
    StackItemType[StackItemType["Buffer"] = 48] = "Buffer";
    StackItemType[StackItemType["Array"] = 64] = "Array";
    StackItemType[StackItemType["Struct"] = 65] = "Struct";
    StackItemType[StackItemType["Map"] = 72] = "Map";
    StackItemType[StackItemType["InteropInterface"] = 96] = "InteropInterface";
})(StackItemType || (StackItemType = {}));
function toStackItemType(type) {
    if (typeof type === "string") {
        return StackItemType[type];
    }
    return type;
}
/**
 * Determine if there's a nested set based on type
 */
export function hasChildren(type) {
    if (type === StackItemType.Array ||
        type === StackItemType.Struct ||
        type === StackItemType.Map) {
        return true;
    }
    return false;
}
function getDefaultValue(type) {
    switch (type) {
        case StackItemType.Array:
        case StackItemType.Struct:
        case StackItemType.Map:
            return [];
        case StackItemType.Boolean:
            return false;
        case StackItemType.Integer:
            return "0";
        case StackItemType.Pointer:
            return 0;
        default:
            return "";
    }
}
/**
 * Object returned as a result of executing a script in the VM.
 */
export class StackItem {
    constructor(obj) {
        var _a, _b;
        if (obj.type === undefined) {
            throw new Error("No type is provided");
        }
        this.type = toStackItemType(obj.type);
        if (obj.value === null || obj.value === undefined) {
            this.value = getDefaultValue(this.type);
            return;
        }
        switch (this.type) {
            case StackItemType.Pointer:
                if (typeof obj.value !== "number") {
                    throw new Error("value of a Pointer StackItem should be a number.");
                }
                this.value = obj.value;
                return;
            case StackItemType.Integer:
                this.value = (_b = (_a = obj.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : "0";
                return;
            case StackItemType.Buffer:
            case StackItemType.ByteString:
                if (typeof obj.value !== "string") {
                    throw new Error("value of a ByteString/Buffer StackItem should be a string.");
                }
                this.value = obj.value;
                return;
            case StackItemType.Boolean:
                this.value = !!obj.value;
                return;
            case StackItemType.Map:
                if (Array.isArray(obj.value) && isStackItemMapLikeArray(obj.value)) {
                    this.value = obj.value.map((i) => ({
                        key: new StackItem(i.key),
                        value: new StackItem(i.value),
                    }));
                }
                throw new Error("Mismatch value for type");
            case StackItemType.Array:
            case StackItemType.Struct:
                if (Array.isArray(obj.value) && isStackItemLikeArray(obj.value)) {
                    this.value = obj.value.map((i) => new StackItem(i));
                }
                throw new Error("Mismatch value for type");
            default:
                throw new Error("unsupported");
        }
    }
    export() {
        const type = StackItemType[this.type];
        switch (this.type) {
            case StackItemType.Array:
            case StackItemType.Struct:
                return {
                    type,
                    value: this.value.map((i) => i.export()),
                };
            case StackItemType.Map:
                return {
                    type,
                    value: this.value.map((kv) => ({
                        key: kv.key.export(),
                        value: kv.value.export(),
                    })),
                };
            default:
                return { type, value: this.value };
        }
    }
}
function isStackItemLike(i) {
    return typeof i === "object" && i !== null && "type" in i;
}
function isStackItemLikeArray(arr) {
    return arr.every(isStackItemLike);
}
function isStackItemMapLikeArray(arr) {
    return arr.every((i) => i && typeof i === "object" && "key" in i && "value" in i);
}
export default StackItem;
//# sourceMappingURL=StackItem.js.map