import BinanceApiConfig from "../../apis/binance/BinanceApiConfig.js";
import APIConfig from "../../apiwrapper/APIConfig.js";
import Serializable from "../../util/Serializable.js";
import SerializableHelper from "../../util/SerializableHelper.js";
import AssetDataCollectionConfig from "../data/asset/AssetDataCollectionConfig.js";

export default class BotConfig extends Serializable {
    /**
     * @type {string} working root
     */
    #workingDirectory = '.';

    /**
     * @type {string} log path relative to working root
     */
    #relativeLogPath = 'logs';

    /**
     * @type {string} data path relative to working root
     */
    #relativeDataPath = 'data';

    /**
     * @type {string} tmp path relative to working root
     */
    #relativeTmpPath = 'tmp';

    /**
     * @type {BinanceApiConfig}
     */
    #apiConfig = new BinanceApiConfig();

    /**
     * @type {AssetDataCollectionConfig}
     */
    #dataCollectionConfig = new AssetDataCollectionConfig(['1s', '1m', '15m', '1h']);

    /**
     * @type {string} chrono unit string; Time until trading should start
     */
    #rampupTime = "15m";

    /**
     * @type {number} max amount of USD, that can be used for trading
     */
    #totalUSDTradingLimit = 500;

    /**
     * @type {number} max USD to spend per trade
     */
    #maxUSDPerTrade = 50.0;

    /**
     * @type {boolean} if rest interface should be enabled
     */
    #enableRestInterface = true;

    /**
     * @type {number} port used for rest interface
     */
    #restInterfacePort = 3044;

    constructor() {
        super();
    }

    /**
     * @param {string} workingDirectory 
     */
    setWorkingDirectory(workingDirectory) {
        this.#workingDirectory = workingDirectory;
    }

    /**
     * @returns {string} working root
     */
    getWorkingDirectory() {
        return this.#workingDirectory;
    }

    /**
     * @param {string} logPath 
     */
    setRelativeLogPath(logPath) {
        this.#relativeLogPath = logPath;
    }

    /**
     * @returns {string} relative log path
     */
    getRelativeLogPath() {
        return this.#relativeLogPath;
    }

    /**
     * @param {string} dataPath 
     */
    setRelativeDataPath(dataPath) {
        this.#relativeDataPath = dataPath;
    }

    /**
     * @returns {string} relative data path
     */
    getRelativeDataPath() {
        return this.#relativeDataPath;
    }

    /**
     * @param {string} tmpPath 
     */
    setRelativeTmpPath(tmpPath) {
        this.#relativeTmpPath = tmpPath;
    }

    /**
     * @returns {string} relative tmp path
     */
    getRelativeTmpPath() {
        return this.#relativeTmpPath;
    }

    /**
     * @returns {string} log directory
     */
    getLogDirectory() {
        return this.#workingDirectory + "/" + this.#relativeLogPath;
    }

    /**
     * @returns {string} data directory
     */
    getDataDirectory() {
        return this.#workingDirectory + "/" + this.#relativeDataPath;
    }

    /**
     * @returns {string} tmp directory
     */
    getTmpDirectory() {
        return this.#workingDirectory + "/" + this.#relativeTmpPath;
    }

    /**
     * @returns {APIConfig}
     */
    getApiConfig() {
        return this.#apiConfig;
    }

    /**
     * @param {APIConfig} apiConfig 
     */
    setApiConfig(apiConfig) {
        this.#apiConfig = apiConfig;
    }

    /**
     * @returns {number} maximum USD, that can be used for trading
     */
    getUsdTradeLimit() {
        return this.#totalUSDTradingLimit;
    }

    /**
     * @param {number} tradeLimit 
     */
    setUsdTradeLimit(tradeLimit) {
        this.#totalUSDTradingLimit = tradeLimit;
    }

    /**
     * @returns {number} usd limit per single trade
     */
    getPerTradeLimit() {
        return this.#maxUSDPerTrade;
    }

    /**
     * @param {number} limit 
     */
    setPerTradeLimit(limit) {
        this.#maxUSDPerTrade = limit;
    }

    /**
     * @returns {boolean}
     */
    isRestInterfaceEnabled(){
        return this.#enableRestInterface;
    }

    /**
     * @param {boolean} enabled 
     */
    setRestInterfaceEnabled(enabled){
        this.#enableRestInterface = enabled;
    }

    /**
     * @returns {number}
     */
    getRestInterfacePort(){
        return this.#restInterfacePort;
    }

    /**
     * @param {number} port 
     */
    setRestInterfacePort(port){
        this.#restInterfacePort = port;
    }

    /**
     * @param {AssetDataCollectionConfig} conf 
     */
    setDataCollectionConfig(conf){
        this.#dataCollectionConfig = conf;
    }

    /**
     * @returns {AssetDataCollectionConfig}
     */
    getDataCollectionConfig(){
        return this.#dataCollectionConfig;
    }

    /**
     * @returns {string} chrono time string
     */
    getRampupTime(){
        return this.#rampupTime;
    }

    /**
     * @param {string} chronoString 
     */
    setRampupTime(chronoString){
        this.#rampupTime = chronoString;
    }

    /**
     * @returns {string} string representation of this object
     */
    toJson() {
        const obj = JSON.parse(super.toJson());
        obj.workingRoot = this.#workingDirectory;
        obj.relativeDataPath = this.#relativeDataPath;
        obj.relativeLogPath = this.#relativeLogPath;
        obj.relativeTmpPath = this.#relativeTmpPath;
        obj.apiConfig = SerializableHelper.serialize(this.#apiConfig);
        obj.totalTradingLimit = this.#totalUSDTradingLimit;
        obj.singleTradeLimit = this.#maxUSDPerTrade;
        obj.restInterfaceEnabled = this.#enableRestInterface;
        obj.restInterfacePort = this.#restInterfacePort;
        obj.assetDataCollectionConfig = SerializableHelper.serialize(this.#dataCollectionConfig);
        obj.rampupTime = this.#rampupTime;

        return JSON.stringify(obj);
    }

    /**
     * @param {string} objString 
     * @returns {BotConfig}
     */
    static fromJson(objString) {
        const obj = JSON.parse(objString);
        const conf = new BotConfig();

        conf.#workingDirectory = obj.workingRoot;
        conf.#relativeDataPath = obj.relativeDataPath;
        conf.#relativeLogPath = obj.relativeLogPath;
        conf.#relativeTmpPath = obj.relativeTmpPath;
        conf.#apiConfig = SerializableHelper.deserialize(obj.apiConfig, APIConfig);
        conf.#totalUSDTradingLimit = obj.totalTradingLimit;
        conf.#maxUSDPerTrade = obj.singleTradeLimit;
        conf.#enableRestInterface = obj.restInterfaceEnabled;
        conf.#restInterfacePort = obj.restInterfacePort;
        conf.#dataCollectionConfig = SerializableHelper.deserialize(obj.assetDataCollectionConfig);
        conf.#rampupTime = obj.rampupTime;

        return conf;
    }
}