"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
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 __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const sinon_1 = __importDefault(require("sinon"));
const internal_1 = require("../../../../../internal");
const mocks_1 = require("../../../../../testUtils/mocks");
const types_1 = require("../../../../../types");
const utilsConversionModule = __importStar(require("../../../../../utils/conversion"));
const utilsInternalModule = __importStar(require("../../../../../utils/internal"));
const Schedules_1 = require("../Schedules");
jest.mock('~/api/entities/CheckpointSchedule', require("../../../../../testUtils/mocks/entities").mockCheckpointScheduleModule('~/api/entities/CheckpointSchedule'));
jest.mock('~/base/Procedure', require("../../../../../testUtils/mocks/procedure").mockProcedureModule('~/base/Procedure'));
describe('Schedules class', () => {
    let context;
    let schedules;
    let ticker;
    let stringToTickerStub;
    beforeAll(() => {
        mocks_1.entityMockUtils.initMocks();
        mocks_1.dsMockUtils.initMocks();
        mocks_1.procedureMockUtils.initMocks();
        ticker = 'SOME_TICKER';
        stringToTickerStub = sinon_1.default.stub(utilsConversionModule, 'stringToTicker');
    });
    afterEach(() => {
        mocks_1.entityMockUtils.reset();
        mocks_1.dsMockUtils.reset();
        mocks_1.procedureMockUtils.reset();
        context = mocks_1.dsMockUtils.getContextInstance();
        const asset = mocks_1.entityMockUtils.getAssetInstance({ ticker });
        schedules = new Schedules_1.Schedules(asset, context);
    });
    afterAll(() => {
        mocks_1.entityMockUtils.cleanup();
        mocks_1.dsMockUtils.cleanup();
        mocks_1.procedureMockUtils.cleanup();
    });
    test('should extend namespace', () => {
        expect(Schedules_1.Schedules.prototype instanceof internal_1.Namespace).toBe(true);
    });
    describe('method: create', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const expectedQueue = 'someQueue';
            const args = {
                start: null,
                period: {
                    unit: types_1.CalendarUnit.Month,
                    amount: 1,
                },
                repetitions: null,
            };
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args: Object.assign({ ticker }, args), transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield schedules.create(args);
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: remove', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should prepare the procedure with the correct arguments and context, and return the resulting transaction queue', () => __awaiter(void 0, void 0, void 0, function* () {
            const expectedQueue = 'someQueue';
            const args = {
                schedule: new bignumber_js_1.default(1),
            };
            mocks_1.procedureMockUtils
                .getPrepareStub()
                .withArgs({ args: Object.assign({ ticker }, args), transformer: undefined }, context)
                .resolves(expectedQueue);
            const queue = yield schedules.remove(args);
            expect(queue).toBe(expectedQueue);
        }));
    });
    describe('method: getOne', () => {
        let getStub;
        let id;
        beforeAll(() => {
            id = new bignumber_js_1.default(1);
        });
        beforeEach(() => {
            getStub = sinon_1.default.stub(schedules, 'get');
        });
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return the requested Checkpoint Schedule', () => __awaiter(void 0, void 0, void 0, function* () {
            const fakeResult = {
                schedule: mocks_1.entityMockUtils.getCheckpointScheduleInstance({ id }),
                details: {
                    remainingCheckpoints: 1,
                    nextCheckpointDate: new Date(),
                },
            };
            getStub.resolves([fakeResult]);
            const result = yield schedules.getOne({ id });
            expect(result).toEqual(fakeResult);
        }));
        test('should throw an error if the Schedule does not exist', () => {
            getStub.resolves([]);
            return expect(schedules.getOne({ id })).rejects.toThrow('The Schedule does not exist');
        });
    });
    describe('method: get', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return the current checkpoint schedules', () => __awaiter(void 0, void 0, void 0, function* () {
            const rawTicker = mocks_1.dsMockUtils.createMockTicker(ticker);
            const id = new bignumber_js_1.default(1);
            const start = new Date('10/14/1987');
            const nextCheckpointDate = new Date('10/14/2030');
            const remaining = new bignumber_js_1.default(2);
            const period = {
                unit: types_1.CalendarUnit.Month,
                amount: 1,
            };
            stringToTickerStub.withArgs(ticker, context).returns(rawTicker);
            sinon_1.default.stub(utilsConversionModule, 'storedScheduleToCheckpointScheduleParams').returns({
                id,
                period,
                start,
                remaining: remaining.toNumber(),
                nextCheckpointDate,
            });
            mocks_1.dsMockUtils.createQueryStub('checkpoint', 'schedules', {
                returnValue: [
                    mocks_1.dsMockUtils.createMockStoredSchedule({
                        schedule: mocks_1.dsMockUtils.createMockCheckpointSchedule({
                            start: mocks_1.dsMockUtils.createMockMoment(start.getTime()),
                            period: mocks_1.dsMockUtils.createMockCalendarPeriod({
                                unit: mocks_1.dsMockUtils.createMockCalendarUnit('Month'),
                                amount: mocks_1.dsMockUtils.createMockU64(1),
                            }),
                        }),
                        id: mocks_1.dsMockUtils.createMockU64(id.toNumber()),
                        at: mocks_1.dsMockUtils.createMockMoment(nextCheckpointDate.getTime()),
                        remaining: mocks_1.dsMockUtils.createMockU32(remaining.toNumber()),
                    }),
                ],
            });
            const result = yield schedules.get();
            expect(result[0].details).toEqual({
                remainingCheckpoints: remaining.toNumber(),
                nextCheckpointDate,
            });
            expect(result[0].schedule.id).toEqual(id);
            expect(result[0].schedule.asset.ticker).toEqual(ticker);
            expect(result[0].schedule.start).toEqual(start);
            expect(result[0].schedule.period).toEqual(period);
        }));
    });
    describe('method: complexityOf', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return the complexity of the passed period', () => {
            const period = {
                unit: types_1.CalendarUnit.Month,
                amount: 7,
            };
            const expected = 2;
            sinon_1.default.stub(utilsInternalModule, 'periodComplexity').withArgs(period).returns(expected);
            expect(schedules.complexityOf(period)).toBe(expected);
        });
    });
    describe('method: currentComplexity', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return the sum of the complexity of all schedules', () => __awaiter(void 0, void 0, void 0, function* () {
            const getStub = sinon_1.default.stub(schedules, 'get');
            getStub.resolves([
                { schedule: mocks_1.entityMockUtils.getCheckpointScheduleInstance({ complexity: 1 }) },
                { schedule: mocks_1.entityMockUtils.getCheckpointScheduleInstance({ complexity: 2 }) },
                { schedule: mocks_1.entityMockUtils.getCheckpointScheduleInstance({ complexity: 2.5 }) },
            ]);
            let result = yield schedules.currentComplexity();
            expect(result).toBe(5.5);
            getStub.resolves([]);
            result = yield schedules.currentComplexity();
            expect(result).toBe(0);
        }));
    });
    describe('method: maxComplexity', () => {
        afterAll(() => {
            sinon_1.default.restore();
        });
        test('should return the maximum complexity from the chain', () => __awaiter(void 0, void 0, void 0, function* () {
            mocks_1.dsMockUtils.createQueryStub('checkpoint', 'schedulesMaxComplexity', {
                returnValue: mocks_1.dsMockUtils.createMockU64(20),
            });
            const result = yield schedules.maxComplexity();
            expect(result).toBe(20);
        }));
    });
});
//# sourceMappingURL=Schedules.js.map