"use strict";
// Copyright 2017-2020 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const bn_js_1 = __importDefault(require("bn.js"));
const util_1 = require("@polkadot/util");
const util_crypto_1 = require("@polkadot/util-crypto");
const create_1 = require("./create");
const BITLENGTH = 64;
/**
 * @name Date
 * @description
 * A wrapper around seconds/timestamps. Internally the representation only has
 * second precicion (aligning with Rust), so any numbers passed an/out are always
 * per-second. For any encoding/decoding the 1000 multiplier would be applied to
 * get it in line with JavaScript formats. It extends the base JS `Date` object
 * and has all the methods available that are applicable to any `Date`
 * @noInheritDoc
 */
class CodecDate extends Date {
    constructor(registry, value = 0) {
        super(CodecDate.decodeDate(value));
        this.registry = registry;
        this.raw = this;
    }
    /** @internal */
    static decodeDate(value) {
        if (value instanceof Date) {
            return value;
        }
        else if (util_1.isU8a(value)) {
            value = util_1.u8aToBn(value.subarray(0, BITLENGTH / 8), true);
        }
        else if (util_1.isString(value)) {
            value = new bn_js_1.default(value, 10, 'le');
        }
        return new Date(util_1.bnToBn(value).toNumber() * 1000);
    }
    /**
     * @description The length of the value when encoded as a Uint8Array
     */
    get encodedLength() {
        return BITLENGTH / 8;
    }
    /**
     * @description returns a hash of the contents
     */
    get hash() {
        return create_1.createType(this.registry, 'Hash', util_crypto_1.blake2AsU8a(this.toU8a(), 256));
    }
    /**
     * @description Checks if the value is an empty value
     */
    get isEmpty() {
        return this.getTime() === 0;
    }
    /**
     * @description Compares the value of the input to see if there is a match
     */
    eq(other) {
        return CodecDate.decodeDate(other).getTime() === this.getTime();
    }
    /**
     * @description Returns the number of bits in the value
     */
    bitLength() {
        return BITLENGTH;
    }
    /**
     * @description Returns the BN representation of the timestamp
     */
    toBn() {
        return new bn_js_1.default(this.toNumber());
    }
    /**
     * @description Returns a hex string representation of the value
     */
    toHex(isLe = false) {
        return util_1.bnToHex(this.toBn(), {
            bitLength: BITLENGTH,
            isLe,
            isNegative: false
        });
    }
    /**
     * @description Converts the Object to JSON, typically used for RPC transfers
     */
    toJSON() {
        // FIXME Return type should be number, but conflicts with Date.toJSON()
        // which returns string
        return this.toNumber();
    }
    /**
     * @description Returns the number representation for the timestamp
     */
    toNumber() {
        return Math.ceil(this.getTime() / 1000);
    }
    /**
     * @description Returns the base runtime type name for this instance
     */
    toRawType() {
        return 'Moment';
    }
    /**
     * @description Returns the string representation of the value
     */
    toString() {
        // only included here since we do not inherit docs
        return super.toString();
    }
    /**
     * @description Encodes the value as a Uint8Array as per the SCALE specifications
     * @param isBare true when the value has none of the type-specific prefixes (internal)
     */
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    toU8a(isBare) {
        return util_1.bnToU8a(this.toNumber(), BITLENGTH, true);
    }
}
exports.default = CodecDate;
