import { BigNumber } from "@ethersproject/bignumber";
export var METADATA_REPLACE = new RegExp("\u0000", "g");
// TODO: remove `as ChainId` in next minor version as we can't ensure it will match our type definition
// note: actual first byte is message type
//     0   [u8; 32] token_address
//     32  u16      token_chain
//     34  [u8; 32] symbol
//     66  [u8; 32] name
//     98  u256     tokenId
//     130 u8       uri_len
//     131 [u8;len] uri
//     ?   [u8; 32] recipient
export var parseNFTPayload = function (arr) {
    var originAddress = arr.slice(1, 1 + 32).toString("hex");
    var originChain = arr.readUInt16BE(33);
    var symbol = Buffer.from(arr.slice(35, 35 + 32))
        .toString("utf8")
        .replace(METADATA_REPLACE, "");
    var name = Buffer.from(arr.slice(67, 67 + 32))
        .toString("utf8")
        .replace(METADATA_REPLACE, "");
    var tokenId = BigNumber.from(arr.slice(99, 99 + 32));
    var uri_len = arr.readUInt8(131);
    var uri = Buffer.from(arr.slice(132, 132 + uri_len))
        .toString("utf8")
        .replace(METADATA_REPLACE, "");
    var target_offset = 132 + uri_len;
    var targetAddress = arr
        .slice(target_offset, target_offset + 32)
        .toString("hex");
    return {
        originAddress: originAddress,
        originChain: originChain,
        symbol: symbol,
        name: name,
        tokenId: tokenId,
        uri: uri,
        targetAddress: targetAddress
    };
};
//     0   u256     amount
//     32  [u8; 32] token_address
//     64  u16      token_chain
//     66  [u8; 32] recipient
//     98  u16      recipient_chain
//     100 u256     fee
export var parseTransferPayload = function (arr) { return ({
    amount: BigNumber.from(arr.slice(1, 1 + 32)).toBigInt(),
    originAddress: arr.slice(33, 33 + 32).toString("hex"),
    originChain: arr.readUInt16BE(65),
    targetAddress: arr.slice(67, 67 + 32).toString("hex"),
    fee: BigNumber.from(arr.slice(99, 99 + 32)).toBigInt(),
}); };
var Reader = /** @class */ (function () {
    function Reader(data) {
        this.offset = 0;
        this.data = Buffer.from(data);
    }
    Reader.prototype.readUint8 = function () {
        var value = this.data.readUInt8(this.offset);
        this.offset += 1;
        return value;
    };
    Reader.prototype.readUint16BE = function () {
        var value = this.data.readUInt16BE(this.offset);
        this.offset += 2;
        return value;
    };
    Reader.prototype.readUint32BE = function () {
        var value = this.data.readUInt32BE(this.offset);
        this.offset += 4;
        return value;
    };
    Reader.prototype.readUint64BE = function () {
        var msb = this.data.readUInt32BE(this.offset);
        var lsb = this.data.readUInt32BE(this.offset + 4);
        var value = msb * (Math.pow(2, 32)) + lsb;
        this.offset += 8;
        return value;
    };
    Reader.prototype.readBytes = function (length) {
        var end = this.offset + length;
        var value = this.data.slice(this.offset, end);
        this.offset = end;
        return value;
    };
    Reader.prototype.remain = function () {
        return this.data.slice(this.offset);
    };
    return Reader;
}());
var Signature = /** @class */ (function () {
    function Signature(index, sig) {
        this.index = index;
        this.sig = sig;
    }
    return Signature;
}());
export { Signature };
var VAA = /** @class */ (function () {
    function VAA(version, guardianSetIndex, signatures, encodedBody, body) {
        this.version = version;
        this.guardianSetIndex = guardianSetIndex;
        this.signatures = signatures;
        this.encodedBody = encodedBody;
        this.body = body;
    }
    VAA.from = function (data) {
        var reader = new Reader(data);
        var version = reader.readUint8();
        var guardianSetIndex = reader.readUint32BE();
        var signatureSize = reader.readUint8();
        var signatures = Array.from(Array(signatureSize).keys()).map(function (_) {
            var sig = reader.readBytes(66);
            var index = sig[0];
            return new Signature(index, sig.slice(1));
        });
        var encodedBody = reader.remain();
        var body = VAABody.from(encodedBody);
        return new VAA(version, guardianSetIndex, signatures, encodedBody, body);
    };
    return VAA;
}());
export { VAA };
var VAABody = /** @class */ (function () {
    function VAABody(timestamp, nonce, emitterChainId, targetChainId, emitterAddress, sequence, consistencyLevel, payload) {
        this.timestamp = timestamp;
        this.nonce = nonce;
        this.emitterChainId = emitterChainId;
        this.targetChainId = targetChainId;
        this.emitterAddress = emitterAddress;
        this.sequence = sequence;
        this.consistencyLevel = consistencyLevel;
        this.payload = payload;
    }
    VAABody.from = function (data) {
        var reader = new Reader(data);
        var timestamp = reader.readUint32BE();
        var nonce = reader.readUint32BE();
        var emitterChainId = reader.readUint16BE();
        var targetChainId = reader.readUint16BE();
        var emitterAddress = reader.readBytes(32);
        var sequence = reader.readUint64BE();
        var consistencyLevel = reader.readUint8();
        var payload = reader.remain();
        return new VAABody(timestamp, nonce, emitterChainId, targetChainId, emitterAddress, sequence, consistencyLevel, payload);
    };
    return VAABody;
}());
export { VAABody };
export function parseVAA(data) {
    return VAA.from(data);
}
//This returns a corrected amount, which accounts for the difference between the VAA
//decimals, and the decimals of the asset.
// const normalizeVaaAmount = (
//   amount: bigint,
//   assetDecimals: number
// ): bigint => {
//   const MAX_VAA_DECIMALS = 8;
//   if (assetDecimals <= MAX_VAA_DECIMALS) {
//     return amount;
//   }
//   const decimalStringVaa = formatUnits(amount, MAX_VAA_DECIMALS);
//   const normalizedAmount = parseUnits(decimalStringVaa, assetDecimals);
//   const normalizedBigInt = BigInt(truncate(normalizedAmount.toString(), 0));
//   return normalizedBigInt;
// };
// function truncate(str: string, maxDecimalDigits: number) {
//   if (str.includes(".")) {
//     const parts = str.split(".");
//     return parts[0] + "." + parts[1].slice(0, maxDecimalDigits);
//   }
//   return str;
// }
