// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { UnlockCondition, UnlockConditionDiscriminator, } from './unlock-condition';
import { Feature, FeatureDiscriminator, NativeTokenFeature } from './feature';
// Temp solution for not double parsing JSON
import { plainToInstance, Type } from 'class-transformer';
import { TokenScheme, TokenSchemeDiscriminator } from './token-scheme';
import { Address, AddressDiscriminator } from '../address';
/**
 * All of the output types.
 */
var OutputType;
(function (OutputType) {
    /** A Basic output. */
    OutputType[OutputType["Basic"] = 0] = "Basic";
    /** An Account output. */
    OutputType[OutputType["Account"] = 1] = "Account";
    /** An Anchor output. */
    OutputType[OutputType["Anchor"] = 2] = "Anchor";
    /** A Foundry output. */
    OutputType[OutputType["Foundry"] = 3] = "Foundry";
    /** An NFT output. */
    OutputType[OutputType["Nft"] = 4] = "Nft";
    /** A Delegation output. */
    OutputType[OutputType["Delegation"] = 5] = "Delegation";
})(OutputType || (OutputType = {}));
/**
 * The base class for outputs.
 */
var Output = /** @class */ (function () {
    /**
     * @param type The type of output.
     * @param amount The amount of the output as big-integer or string.
     */
    function Output(type, amount) {
        this.type = type;
        if (typeof amount == 'bigint') {
            this.amount = amount.toString(10);
        }
        else {
            this.amount = amount;
        }
    }
    /**
     * Get the amount of the output.
     */
    Output.prototype.getAmount = function () {
        return BigInt(this.amount);
    };
    /**
     * Parse an output from a plain JS JSON object.
     */
    Output.parse = function (data) {
        if (data.type == OutputType.Basic) {
            return plainToInstance(BasicOutput, data);
        }
        else if (data.type == OutputType.Account) {
            return plainToInstance(AccountOutput, data);
        }
        else if (data.type == OutputType.Anchor) {
            return plainToInstance(AnchorOutput, data);
        }
        else if (data.type == OutputType.Foundry) {
            return plainToInstance(FoundryOutput, data);
        }
        else if (data.type == OutputType.Nft) {
            return plainToInstance(NftOutput, data);
        }
        else if (data.type == OutputType.Delegation) {
            return plainToInstance(DelegationOutput, data);
        }
        throw new Error('Invalid JSON');
    };
    return Output;
}());
/**
 * The base class for common outputs.
 */
var CommonOutput = /** @class */ (function (_super) {
    __extends(CommonOutput, _super);
    /**
     * @param type The type of output.
     * @param amount The amount of the output.
     * @param unlockConditions Conditions to unlock the output.
     */
    function CommonOutput(type, amount, unlockConditions) {
        var _this = _super.call(this, type, amount) || this;
        _this.unlockConditions = unlockConditions;
        return _this;
    }
    /**
     * The native token held by the output.
     */
    CommonOutput.prototype.getNativeToken = function () {
        if (!this.features) {
            return undefined;
        }
        for (var _i = 0, _a = this.features; _i < _a.length; _i++) {
            var feature = _a[_i];
            if (feature instanceof NativeTokenFeature) {
                return feature.asNativeToken();
            }
        }
        return undefined;
    };
    __decorate([
        Type(function () { return UnlockCondition; }, {
            discriminator: UnlockConditionDiscriminator
        })
    ], CommonOutput.prototype, "unlockConditions");
    __decorate([
        Type(function () { return Feature; }, {
            discriminator: FeatureDiscriminator
        })
    ], CommonOutput.prototype, "features");
    return CommonOutput;
}(Output));
/**
 * A Basic output.
 */
var BasicOutput = /** @class */ (function (_super) {
    __extends(BasicOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param mana The mana of the output.
     * @param unlockConditions The unlock conditions for the output.
     */
    function BasicOutput(amount, mana, unlockConditions) {
        var _this = _super.call(this, OutputType.Basic, amount, unlockConditions) || this;
        _this.mana = mana;
        return _this;
    }
    return BasicOutput;
}(CommonOutput));
/**
 * Base class for immutable feature outputs.
 */
var ImmutableFeaturesOutput = /** @class */ (function (_super) {
    __extends(ImmutableFeaturesOutput, _super);
    /**
     * @param type The type of output.
     * @param amount The amount of the output.
     * @param unlockConditions The unlock conditions for the output.
     */
    function ImmutableFeaturesOutput(type, amount, unlockConditions) {
        return _super.call(this, type, amount, unlockConditions) || this;
    }
    __decorate([
        Type(function () { return Feature; }, {
            discriminator: FeatureDiscriminator
        })
    ], ImmutableFeaturesOutput.prototype, "immutableFeatures");
    return ImmutableFeaturesOutput;
}(CommonOutput));
/**
 * An Account output.
 */
var AccountOutput = /** @class */ (function (_super) {
    __extends(AccountOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param mana The amount of stored mana.
     * @param accountId The account ID as hex-encoded string.
     * @param foundryCounter A counter that denotes the number of foundries created by this account output.
     * @param unlockConditions The unlock conditions of the output.
     */
    function AccountOutput(amount, mana, accountId, foundryCounter, unlockConditions) {
        var _this = _super.call(this, OutputType.Account, amount, unlockConditions) || this;
        _this.accountId = accountId;
        _this.foundryCounter = foundryCounter;
        _this.mana = mana;
        return _this;
    }
    return AccountOutput;
}(ImmutableFeaturesOutput));
/**
 * An Anchor output.
 */
var AnchorOutput = /** @class */ (function (_super) {
    __extends(AnchorOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param mana The amount of stored mana.
     * @param anchorId The anchor ID as hex-encoded string.
     * @param stateIndex A counter that must increase by 1 every time the anchor output is state transitioned.
     * @param unlockConditions The unlock conditions of the output.
     */
    function AnchorOutput(amount, mana, anchorId, stateIndex, unlockConditions) {
        var _this = _super.call(this, OutputType.Account, amount, unlockConditions) || this;
        _this.anchorId = anchorId;
        _this.stateIndex = stateIndex;
        _this.mana = mana;
        return _this;
    }
    return AnchorOutput;
}(ImmutableFeaturesOutput));
/**
 * A Foundry output.
 */
var FoundryOutput = /** @class */ (function (_super) {
    __extends(FoundryOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param serialNumber The serial number of the Foundry with respect to the controlling account.
     * @param unlockConditions The unlock conditions of the output.
     * @param tokenScheme The token scheme for the Foundry.
     */
    function FoundryOutput(amount, serialNumber, unlockConditions, tokenScheme) {
        var _this = _super.call(this, OutputType.Foundry, amount, unlockConditions) || this;
        _this.serialNumber = serialNumber;
        _this.tokenScheme = tokenScheme;
        return _this;
    }
    __decorate([
        Type(function () { return TokenScheme; }, {
            discriminator: TokenSchemeDiscriminator
        })
    ], FoundryOutput.prototype, "tokenScheme");
    return FoundryOutput;
}(ImmutableFeaturesOutput));
/**
 * An NFT output.
 */
var NftOutput = /** @class */ (function (_super) {
    __extends(NftOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param mana The amount of stored mana.
     * @param nftId The NFT ID as hex-encoded string.
     * @param unlockConditions The unlock conditions of the output.
     */
    function NftOutput(amount, mana, nftId, unlockConditions) {
        var _this = _super.call(this, OutputType.Nft, amount, unlockConditions) || this;
        _this.nftId = nftId;
        _this.mana = mana;
        return _this;
    }
    return NftOutput;
}(ImmutableFeaturesOutput));
/**
 * A Delegation output.
 */
var DelegationOutput = /** @class */ (function (_super) {
    __extends(DelegationOutput, _super);
    /**
     * @param amount The amount of the output.
     * @param delegatedAmount The amount of delegated coins.
     * @param delegationId Unique identifier of the Delegation Output, which is the BLAKE2b-256 hash of the Output ID that created it.
     * @param validatorAddress The Account address of the validator to which this output is delegating.
     * @param startEpoch The index of the first epoch for which this output delegates.
     * @param endEpoch The index of the last epoch for which this output delegates.
     * @param unlockConditions The unlock conditions of the output.
     */
    function DelegationOutput(amount, delegatedAmount, delegationId, validatorAddress, startEpoch, endEpoch, unlockConditions) {
        var _this = _super.call(this, OutputType.Delegation, amount) || this;
        _this.delegatedAmount = delegatedAmount;
        _this.delegationId = delegationId;
        _this.validatorAddress = validatorAddress;
        _this.startEpoch = startEpoch;
        _this.endEpoch = endEpoch;
        _this.unlockConditions = unlockConditions;
        return _this;
    }
    __decorate([
        Type(function () { return Address; }, {
            discriminator: AddressDiscriminator
        })
    ], DelegationOutput.prototype, "validatorAddress");
    __decorate([
        Type(function () { return UnlockCondition; }, {
            discriminator: UnlockConditionDiscriminator
        })
    ], DelegationOutput.prototype, "unlockConditions");
    return DelegationOutput;
}(Output));
var OutputDiscriminator = {
    property: 'type',
    subTypes: [
        { value: BasicOutput, name: OutputType.Basic },
        { value: AccountOutput, name: OutputType.Account },
        { value: AnchorOutput, name: OutputType.Anchor },
        { value: FoundryOutput, name: OutputType.Foundry },
        { value: NftOutput, name: OutputType.Nft },
        { value: DelegationOutput, name: OutputType.Delegation },
    ]
};
export { OutputDiscriminator, Output, OutputType, CommonOutput, BasicOutput, AccountOutput, AnchorOutput, FoundryOutput, NftOutput, DelegationOutput, };
//# sourceMappingURL=output.js.map