import { num2hexstring, num2VarInt, StringStream, HexString } from "../../u";
import { TxAttrUsage } from "./txAttrUsage";
const maxTransactionAttributeSize = 252;
export function toTxAttrUsage(type) {
    if (typeof type === "string") {
        if (type in TxAttrUsage) {
            return TxAttrUsage[type];
        }
        throw new Error(`${type} not found in TxAttrUsage!`);
    }
    else if (typeof type === "number") {
        if (TxAttrUsage.Url !== type) {
            throw new Error(`${type} not found in TxAttrUsage!`);
        }
    }
    return type;
}
/**
 * An attribute that is used to decorate the transaction.
 * Used for appending additional information to the transaction.
 *
 * For example, a remark is attached as an attribute.
 */
export class TransactionAttribute {
    constructor(obj = {}) {
        if (!obj.usage || !obj.data) {
            throw new Error("TransactionAttribute requires usage and data fields");
        }
        const { usage, data } = obj;
        this.usage = toTxAttrUsage(usage);
        this.data = HexString.fromHex(data);
    }
    static deserialize(hex) {
        const ss = new StringStream(hex);
        return this.fromStream(ss);
    }
    static fromJson(input) {
        return new TransactionAttribute({
            usage: toTxAttrUsage(input.usage),
            data: HexString.fromBase64(input.data, true),
        });
    }
    static fromStream(ss) {
        const usage = parseInt(ss.read(1), 16);
        const data = ss.readVarBytes();
        if (data.length > maxTransactionAttributeSize * 2) {
            throw new Error("Data too big! Only 252 bytes allowed in data");
        }
        return new TransactionAttribute({ usage, data });
    }
    get size() {
        return (1 + num2VarInt(this.data.byteLength).length / 2 + this.data.byteLength);
    }
    /**
     * Constructs a Url Attribute
     * @param url - URL string in ASCII
     */
    static Url(url) {
        return new TransactionAttribute({
            usage: TxAttrUsage.Url,
            data: HexString.fromAscii(url),
        });
    }
    get [Symbol.toStringTag]() {
        return "TransactionAttribute";
    }
    serialize() {
        if (this.data.length > maxTransactionAttributeSize) {
            throw new Error(`Data size too big!`);
        }
        let out = num2hexstring(this.usage);
        out += num2VarInt(this.data.byteLength);
        out += this.data;
        return out;
    }
    export() {
        return {
            usage: this.usage,
            data: this.data.toBigEndian(),
        };
    }
    toJson() {
        return {
            usage: TxAttrUsage[this.usage],
            data: this.data.toBase64(true),
        };
    }
    equals(other) {
        var _a, _b;
        return (this.usage === toTxAttrUsage((_a = other.usage) !== null && _a !== void 0 ? _a : 0) &&
            this.data.equals((_b = other.data) !== null && _b !== void 0 ? _b : ""));
    }
}
export default TransactionAttribute;
//# sourceMappingURL=TransactionAttribute.js.map