import APIConfig from "../../apiwrapper/APIConfig.js";

export default class BinanceApiConfig extends APIConfig {
    static #API_KEY = 'f7x9yfDoEH6dSRLwU78g4uSZvDZHCYiY3rcSgI2G96E5hsQc6Zet7LqQK3heLNIM';
    static #API_SECRET = 'FIIHHjBHN9I5u00z0DNLRoR4uRTnOL2fqqDAXw7F0uV0fp3K5popSjAAIuVTA2Vt';

    static #TESTNET_API_KEY = 'XajblTfRZWrX7vwXhvXmmxruRqQJQUxZEhdDYVdQ89h0Xumapyw8foLCvTTlZVmE';
    static #TESTNET_API_SECRET = 'blhx3VztCsslGXERTl8A1pxvpT6GvMAj5Qgys32azzL3OfYEBhhKVTKnXrHYiATt';
    static #TESTNET_URL = 'https://testnet.binance.vision';
    static #TESTNET_WS_URL = 'wss://testnet.binance.vision/ws';

    #alternativeKey = null;
    #alternativeSecret = null;
    #alternativeWSURL = null;
    #alternativeRestURL = null;

    constructor(altKey, altSecret) {
        super();
        this.#alternativeKey = altKey;
        this.#alternativeSecret = altSecret
    }

    /**
     * @returns {BinanceApiConfig} main net config
     */
    static createMainNetConfig() {
        return new BinanceApiConfig();
    }

    /**
     * @returns {BinanceApiConfig} test net config
     */
    static createTestNetConfig() {
        const conf = new BinanceApiConfig(BinanceApiConfig.#TESTNET_API_KEY, BinanceApiConfig.#TESTNET_API_SECRET);
        conf.setTestNet(true);

        return conf;
    }

    /**
     * @returns {import("binance").RestClientOptions}
     */
    getRestClientConfig() {
        /**
         * @type {import("binance").RestClientOptions}
         */
        const config = {
            "api_key": this.getKey(),
            "api_secret": this.getSecret(),
            "disableTimeSync": false
        };

        if (this.isTestNet()) {
            config.baseUrl = BinanceApiConfig.#TESTNET_URL;
        }

        return config;
    }

    /**
     * @returns {import("binance").WSClientConfigurableOptions}
     */
    getWSClientConfig() {
        /**
         * @type {import("binance").WSClientConfigurableOptions}
         */
        const config = {
            "api_key": this.getKey(),
            "api_secret": this.getSecret(),
            "beautify": true
        };

        if (this.isTestNet()) {
            config.wsUrl = BinanceApiConfig.#TESTNET_WS_URL;
            config.baseUrl = BinanceApiConfig.#TESTNET_URL;
        }

        return config;
    }

    /**
     * @param {string} url alternative websocket url
     */
    setWSUrl(url) {
        this.#alternativeWSURL = url;
    }

    /**
     * @param {string} url alternative rest api url 
     */
    setRestUrl(url) {
        this.#alternativeRestURL = url;
    }

    /**
     * @returns {string}
     */
    getWSUrl() {
        return this.#alternativeWSURL;
    }

    /**
     * @returns {string}
     */
    getRestUrl() {
        return this.#alternativeRestURL;
    }

    /**
     * @returns {string} api key
     */
    getKey() {
        if (this.#alternativeKey) {
            return this.#alternativeKey;
        }

        return BinanceApiConfig.#API_KEY;
    }

    /**
     * @returns {string} api secret
     */
    getSecret() {
        if (this.#alternativeSecret) {
            return this.#alternativeSecret;
        }

        return BinanceApiConfig.#API_SECRET;
    }

    /**
     * @returns {string} string representation of this object
     */
    toJson() {
        const obj = JSON.parse(super.toJson());
        obj.alternativeKey = this.#alternativeKey;
        obj.alternativeSecret = this.#alternativeSecret;
        obj.alternativeWsUrl = this.#alternativeWSURL;
        obj.alternativeRestUrl = this.#alternativeRestURL;
        
        return JSON.stringify(obj);
    }

    /**
     * @param {string} objString 
     * @returns {BinanceApiConfig}
     */
    static fromJson(objString) {
        const config = JSON.parse(objString);
        const conf = config.testNet ? BinanceApiConfig.createTestNetConfig() : BinanceApiConfig.createMainNetConfig();
        conf.setRestUrl(config.alternativeRestUrl);
        conf.setWSUrl(config.alternativeWsUrl);
        conf.#alternativeKey = config.alternativeKey;
        conf.#alternativeSecret = config.alternativeSecret;

        return conf;
    }
}