"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheckpointSchedule = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const dayjs_1 = __importDefault(require("dayjs"));
const internal_1 = require("../../../internal");
const types_1 = require("../../../types");
const conversion_1 = require("../../../utils/conversion");
const internal_2 = require("../../../utils/internal");
const notExistsMessage = 'Schedule no longer exists. It was either removed or it expired';
/**
 * Represents a Checkpoint Schedule for an Asset. Schedules can be set up to create Checkpoints at regular intervals
 */
class CheckpointSchedule extends internal_1.Entity {
    /**
     * @hidden
     */
    constructor(args, context) {
        const { period, start, remaining, nextCheckpointDate } = args, identifiers = __rest(args, ["period", "start", "remaining", "nextCheckpointDate"]);
        super(identifiers, context);
        const { id, ticker } = identifiers;
        const noPeriod = period.amount.isZero();
        this.id = id;
        this.asset = new internal_1.Asset({ ticker }, context);
        this.period = noPeriod ? null : period;
        this.start = start;
        this.complexity = internal_2.periodComplexity(period);
        if (remaining.isZero() && !noPeriod) {
            this.expiryDate = null;
        }
        else if (!this.period) {
            this.expiryDate = start;
        }
        else {
            const { amount, unit } = period;
            this.expiryDate = dayjs_1.default(nextCheckpointDate)
                .add(amount.multipliedBy(remaining.minus(1)).toNumber(), unit)
                .toDate();
        }
    }
    /**
     * @hidden
     * Check if a value is of type [[UniqueIdentifiers]]
     */
    static isUniqueIdentifiers(identifier) {
        const { id, ticker } = identifier;
        return id instanceof bignumber_js_1.default && typeof ticker === 'string';
    }
    /**
     * Retrieve information specific to this Schedule
     */
    details() {
        return __awaiter(this, void 0, void 0, function* () {
            const { context: { polymeshApi: { query: { checkpoint }, }, }, id, context, asset: { ticker }, } = this;
            const rawSchedules = yield checkpoint.schedules(conversion_1.stringToTicker(ticker, context));
            const schedule = rawSchedules.find(({ id: scheduleId }) => conversion_1.u64ToBigNumber(scheduleId).eq(id));
            if (!schedule) {
                throw new internal_1.PolymeshError({
                    code: types_1.ErrorCode.DataUnavailable,
                    message: notExistsMessage,
                });
            }
            const { at, remaining } = schedule;
            return {
                remainingCheckpoints: conversion_1.u32ToBigNumber(remaining),
                nextCheckpointDate: conversion_1.momentToDate(at),
            };
        });
    }
    /**
     * Retrieve all Checkpoints created by this Schedule
     */
    getCheckpoints() {
        return __awaiter(this, void 0, void 0, function* () {
            const { context: { polymeshApi: { query: { checkpoint }, }, }, context, asset: { ticker }, id, } = this;
            const exists = yield this.exists();
            if (!exists) {
                throw new internal_1.PolymeshError({
                    code: types_1.ErrorCode.DataUnavailable,
                    message: notExistsMessage,
                });
            }
            const result = yield checkpoint.schedulePoints(conversion_1.stringToTicker(ticker, context), conversion_1.bigNumberToU64(id, context));
            return result.map(rawId => new internal_1.Checkpoint({ id: conversion_1.u64ToBigNumber(rawId), ticker }, context));
        });
    }
    /**
     * Determine whether this Checkpoint Schedule exists on chain
     */
    exists() {
        return __awaiter(this, void 0, void 0, function* () {
            const { context: { polymeshApi: { query: { checkpoint }, }, }, context, asset: { ticker }, id, } = this;
            const rawSchedules = yield checkpoint.schedules(conversion_1.stringToTicker(ticker, context));
            const exists = rawSchedules.find(({ id: scheduleId }) => conversion_1.u64ToBigNumber(scheduleId).eq(id));
            return !!exists;
        });
    }
    /**
     * Return the Schedule's static data
     */
    toJson() {
        const { asset, id, expiryDate, complexity, start, period } = this;
        return internal_2.toHumanReadable({
            ticker: asset,
            id,
            start,
            expiryDate,
            period,
            complexity,
        });
    }
}
exports.CheckpointSchedule = CheckpointSchedule;
//# sourceMappingURL=index.js.map