#!/usr/bin/env node

'use strict';

/**
 * Utilities RPC Prototype
 *
 * (c) 2016 VISTA Data Project
 */

/*
 * Basic setup
 */
const rpcEmulatorModel = require('./rpcEmulatorUtilitiesModel').rpcEmulatorModel;
const unitTestUtils = require('../unitTestUtils');

describe('testUtilitiesRPCs', () => {
    let rpcE;
    let rpcR;

    beforeAll(() => {
        const res = unitTestUtils.beforeAllScript(rpcEmulatorModel);
        rpcE = res.rpcE;
        rpcR = res.rpcR;
    });

    const dtRPCTestCases = [
        {
            description: 'Get the current time using "NOW"',
            args: ['NOW'],
            expected: 'VALID',
        }, {
            description: 'Get the current time using "N"',
            args: ['N'],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with hour delta using "N+1H"',
            args: ['N+1H'],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with hour delta using "N-3H"',
            args: ['N-3H'],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with minute delta using "N+1\'"',
            args: ['N+1\''],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with minute delta using "N-3\'"',
            args: ['N-3\''],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with day delta using "N+1D"',
            args: ['N+1D'],
            expected: 'VALID',
        }, {
            description: 'Get the current date/time with day delta using "N-3D"',
            args: ['N-3D'],
            expected: 'VALID',
        }, {
            description: 'Get the current date using "TODAY"',
            args: ['TODAY'],
            expected: 'VALID',
        }, {
            description: 'Get the current date using "T"',
            args: ['T'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with day delta using "T+1"',
            args: ['T+1'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with day delta using "T-1"',
            args: ['T-1'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with day delta using "T+1D"',
            args: ['T+1D'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with day delta using "T-1D"',
            args: ['T-1D'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with month delta using "T+1M"',
            args: ['T+1M'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with month delta using "T-5M"',
            args: ['T-5M'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with year delta using "T+1W"',
            args: ['T+1W'],
            expected: 'VALID',
        }, {
            description: 'Get the current date with year delta using "T-5W"',
            args: ['T-5W'],
            expected: 'VALID',
        }, {
            description: 'Get an invalid date/time',
            args: [''],
            expected: -1,
        }, {
            description: 'Get the date/time today at noon using "NOON"',
            args: ['NOON'],
            expected: 'VALID',
        }, {
            description: 'Get the date/time today at midnight using "MID"',
            args: ['MID'],
            expected: 'VALID',
        }, {
            description: 'Get the date in MM/DD/YYYY format',
            args: ['03/29/2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in DD/MM/YYYY format (international style) with option I',
            args: ['29/3/2016', 'TSI'],
            expected: 3160329,
        }, {
            description: 'Get the date in dd MMM YYYY format',
            args: ['29 MAR 2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in dd-MMM-YYYY format',
            args: ['29-mar-2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in ddMMMYYYY format',
            args: ['29MAR2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in MMM dd, YYYY format',
            args: ['MAR 29, 2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in MMM dd,YYYY format',
            args: ['mar 29,2016'],
            expected: 3160329,
        }, {
            description: 'Get the date in mm/dd format',
            args: ['11/3'],
            expected: 3171103,
        }, {
            description: 'Get the date in dd/mm format (international style) with option I',
            args: ['11/3', 'TSI'],
            expected: 3170311,
        }, {
            description: 'Get the date in MMM dd format',
            args: ['MAR 03'],
            expected: 3170303,
        }, {
            description: 'Get a date in MMM yyyy format',
            args: ['MAR 2015'],
            expected: 3150300,
        }, {
            description: 'Get a date in mmddyy format',
            args: ['090373'],
            expected: 2730903,
        }, {
            description: 'Get a date in ddmmyy format (international style) with option I',
            args: ['090373', 'TSI'],
            expected: 2730309,
        }, {
            description: 'Get a date in mmddyy format with option N',
            args: ['090373', 'TSN'],
            expected: -1,
        }, {
            description: 'Get a date in mmddyyyy format',
            args: ['01022018'],
            expected: 3180102,
        }, {
            description: 'Get a date in ddmmyyyy format (international style) with option I',
            args: ['01022018', 'TSI'],
            expected: 3180201,
        }, {
            description: 'Get a date in mmddyyyy format with option N',
            args: ['01022018', 'TSN'],
            expected: -1,
        }, {
            description: 'Get a date in fileman format',
            args: ['3160804'],
            expected: 3160804,
        }, {
            description: 'Get a date/time in fileman format',
            args: ['3170208.0500'],
            expected: 3170208.0500,
        }, {
            description: 'Get time value in HH:MM format',
            args: ['08/04/2016@09:57'],
            expected: 3160804.0957,
        }, {
            description: 'Get time value in HH:MM:SS PM format',
            args: ['Aug 4,2016@9:57:02 PM'],
            expected: 3160804.215702,
        }, {
            description: 'Get time value in HH:MM:SS P.M format',
            args: ['Aug 4,2016@9:57:02 P.M'],
            expected: 3160804.215702,
        }, {
            description: 'Get time value in HH:MM:SSP.M. format',
            args: ['Aug 4,2016@9:57:02P.M.'],
            expected: 3160804.215702,
        }, {
            description: 'Get time value in HH:MM AM format, where the hour is incorrectly represented',
            args: ['Aug 4,2016@21:57 AM'],
            expected: 3160804.0957,
        }, {
            description: 'Hardhats - Get the date for "July 20, 1999"',
            args: ['July 20, 1999'],
            expected: 2990720,
        }, {
            description: 'Hardhats - Get the date for "April 07 2017"',
            args: ['Apr 07 2017'],
            expected: 3170407,
        }, {
            description: 'Hardhats - Get the date for "Apr 07 2017"',
            args: ['April 07 2017'],
            expected: 3170407,
        }, {
            description: 'Hardhats - Get the date for "7/20/99"',
            args: ['7/20/99'],
            expected: 2990720,
        }, {
            description: 'Hardhats - Get the date for "20 JUL 99"',
            args: ['20 JUL 99'],
            expected: 2990720,
        }, {
            description: 'Hardhats - Get the date for "10jul99"',
            args: ['10jul99'],
            expected: 2990710,
        }, {
            description: 'Hardhats - Get the date for "10 jul 99"',
            args: ['10 jul 99'],
            expected: 2990710,
        }, {
            description: 'Hardhats - Get the date for "1999"',
            args: ['1999'],
            expected: 2990000,
        }, {
            description: 'Hardhats - Get the date for "20 JUL 99@4PM"',
            args: ['20 JUL 99@4PM'],
            expected: 2990720.16,
        }, {
            description: 'Hardhats - Get the date/time for 20 JUL 99@330',
            args: ['20-JUL-99@330'],
            expected: 2990720.1530,
        }, {
            description: 'Hardhats - Get the date/time for 20 JUL 99@3:30',
            args: ['20-JUL-99@330'],
            expected: 2990720.1530,
        }, {
            description: 'Hardhats - Get the date/time for 20JUL99@600',
            args: ['20JUL99@600'],
            expected: 2990720.06,
        }, {
            description: 'Hardhats - Get the date/time for 20JUL99@065930',
            args: ['20JUL99@065930'],
            expected: 2990720.065930,
        }, {
            description: 'Hardhats - Get the date for 1/15 - with "future" flag',
            args: ['1/15', 'TSF'],
            expected: "VALID",
        }, {
            description: 'Hardhats - Get the date for 1/15 - with "past" flag',
            args: ['8/15', 'TSP'],
            expected: "VALID",
        }, {
            description: 'Hardhats - Get the date for 1/15/69 - with "future" flag',
            args: ['1/15/69', 'TSF'],
            expected: "VALID",
        }, {
            description: 'Hardhats - Get the date for 1/15/23 - with "past" flag',
            args: ['1/15/23', 'TSP'],
            expected: "VALID",
        }, {
            description: 'Hardhats - Get the date for 7-05 - should give us mm/yy',
            args: ['7-05', 'M'],
            expected: 3050700,
        }, {
            description: 'Hardhats - Get the date for 7/05 - should give us mm-yy',
            args: ['7/05', 'M'],
            expected: 3050700,
        }, {
            description: 'Hardhats - Get the date for 7/2005 - should give us mm/yyyy',
            args: ['7/2005'],
            expected: 3050700,
        }, {
            description: 'Hardhats - Y2K: Get the date for 1/1/19',
            args: ['1/1/19'],
            expected: 3190101,
        }, {
            description: 'Hardhats - Y2K: Get the date for 1/1/20',
            args: ['1/1/20'],
            expected: 3200101,
        }, {
            description: 'Get an invalid date',
            args: ['11/2/10554'],
            expected: -1,
        }, {
            description: 'Get a date only with the "R" option set',
            args: ['11/2/1980', 'R'],
            expected: -1,
        }, {
            description: 'Get a date/time with the "R" option set',
            args: ['20-JUL-99@330', 'R'],
            expected: 2990720.1530,
        }, {
            description: 'Get a year only with "N" set',
            args: ['1999', 'N'],
            expected: -1,
        }, {
            description: 'Get a fileman date only with "N" set',
            args: ['3200101', 'N'],
            expected: -1,
        }, {
            description: 'Get a mmddyyyy date only with "N" set',
            args: ['01012001', 'N'],
            expected: -1,
        }, {
            description: 'Get a mmddyy date only with "N" set',
            args: ['010101', 'N'],
            expected: -1,
        }, {
            description: 'Get a date in fileman format with option N',
            args: ['3160804', 'TSN'],
            expected: -1,
        }, {
            description: 'Get a date in fileman format with option N',
            args: ['3160804.123455', 'TSN'],
            expected: 3160804.123455,
        }, {
            description: 'Get a date in MMM yyyy format with options X',
            args: ['MAR 2015', 'TSX'],
            expected: -1,
        }, {
            description: 'Hardhats - Get the date for 7-05-2005 - with "month and year only" flag',
            args: ['7-05-2005', 'M'],
            expected: -1,
        }, {
            description: 'MIDNIGHT with M option set',
            args: ['MID', 'M'],
            expected: -1,
        }, {
            description: 'NOON with M option set',
            args: ['NOON', 'M'],
            expected: -1,
        }, {
            description: 'dd MMM yyyy with M option set',
            args: ['23 JUL 1998', 'M'],
            expected: -1,
        }, {
            description: 'MMM dd,yyyy with M option set',
            args: ['jul 23,1998', 'M'],
            expected: -1,
        }, {
            description: 'MMM dd with M option set',
            args: ['23 jul', 'M'],
            expected: 3230700,
        }, {
            description: 'dd MMM with M option set',
            args: ['jul 10', 'M'],
            expected: 3100700,
        }, {
            description: 'yyyy M option set',
            args: ['1999', 'M'],
            expected: 2990000,
        }, {
            description: 'Get a mmddyyyy date only with "M" set',
            args: ['01012001', 'M'],
            expected: -1,
        }, {
            description: 'Get a mmddyy date only with "M" set',
            args: ['010101', 'M'],
            expected: -1,
        }, {
            description: 'Get a date in fileman format with option M',
            args: ['3160804', 'M'],
            expected: -1,
        }, {
            description: 'Get a date/time in fileman format with option M',
            args: ['3160804.160054', 'M'],
            expected: -1,
        }, {
            description: 'Get a date with an incorrect month',
            args: ['1 FOO 2011'],
            expected: -1,
        }, {
            description: 'Get a date with an incorrect month',
            args: ['BLAHBUERY 10, 2017'],
            expected: -1,
        },
    ];

    // *********************************************************************************************
    // Run all the test cases described above. Each test case above will be run as follows:
    //    * RPC Emulator output with 'args' compared to the 'expected' value
    //        * if 'expected' is 'VALID', the test case runner will only make sure that the
    //          value is not -1
    //    * RPC Runner output compared against the RPC Emulator output
    // *********************************************************************************************
    dtRPCTestCases.forEach((testCase) => {
        it(`ORWU DT: ${testCase.description} - Compare emulator results against expected value`, () => {
            const emulatorRes = rpcE.run('ORWU DT', testCase.args);
            expect(emulatorRes.result).toBeDefined();
            if (testCase.expected === 'VALID') {
                expect(emulatorRes.result).not.toEqual(-1);
            } else {
                expect(emulatorRes.result).toEqual(testCase.expected);
            }
        });

        it(`ORWU DT: ${testCase.description} - Compare runner results against emulator results`, () => {
            const emulatorRes = rpcE.run('ORWU DT', testCase.args);
            const runnerRes = rpcR.run('ORWU DT', testCase.args);
            expect(runnerRes.result).toEqual(emulatorRes.result);
        });
    });

    it('Use rpc Util to get time', () => {
        const res = rpcE.run('ORWU VALDT', ['Aug 4,2016@21:57']);
        expect(res.result).toBeDefined();
        expect(res.result).toEqual(3160804.2157);

        const runnerRes = rpcR.run('ORWU VALDT', ['Aug 4,2016@21:57']);
        expect(runnerRes.result).toEqual(res.result);

        const res1 = rpcE.run('ORWU VALDT', ['Feb 8,2017@05:00', 'TS']);
        expect(res1.result).toEqual(3170208.0500);

        const runnerRes1 = rpcR.run('ORWU VALDT', ['Feb 8,2017@05:00', 'TS']);
        expect(runnerRes1.result).toEqual(res1.result);
    });

    it('Use rpc Util to convert time', () => {
        const res = rpcE.run('GMV CONVERT DATE', ['08/04/2016@9:57PM']);
        expect(res.result).toBeDefined();
        expect(res.result).toEqual('3160804.2157^AUG 04, 2016@21:57:00');

        const runnerRes = rpcR.run('GMV CONVERT DATE', ['08/04/2016@9:57PM']);
        expect(runnerRes.result).toEqual(res.result);
    });

    it('Use rpc Util to get current time', () => {
        const res = rpcE.run('GMV GET CURRENT TIME', []);
        expect(res.result).toBeDefined();

        const runnerRes = rpcR.run('GMV GET CURRENT TIME', []);
        expect(runnerRes.result).toEqual(res.result);
    });

    it('Use rpc Util to get clinic appointment date ranges', () => {
        const res = rpcE.run('ORWPT CLINRNG', []);
        expect(res.result).toBeDefined();
        const dates = ['T;T^Today',
            'T+1;T+1^Tomorrow',
            'T-1;T-1^Yesterday',
            'T-7;T^Past Week',
            'T-31;T^Past Month',
            'S^Specify Date Range...',
        ];
        expect(res.result).toEqual(dates);

        const runnerRes = rpcR.run('ORWPT CLINRNG', []);
        expect(runnerRes.result).toEqual(res.result);
    });

    it('Use rpc Util to get null list', () => {
        const res = rpcE.run('ORQ NULL LIST', []);
        expect(res.result).toBeDefined();
        expect(res.result).toEqual(['']);

        const runnerRes = rpcR.run('ORQ NULL LIST', []);
        expect(runnerRes.result).toEqual(res.result);
    });

    it('Use rpc Util to ORWPT16 PSCNVT', () => {
        const res = rpcE.run('ORWPT16 PSCNVT', []);
        expect(res.result).toBeDefined();
        expect(res.result).toEqual(0);

        const runnerRes = rpcR.run('ORWPT16 PSCNVT', []);
        expect(runnerRes.result).toEqual(res.result);
    });


    afterAll(() => {
        unitTestUtils.afterAllScript();
    });
});
