package se.koc.trader;

import se.koc.trader.api.ExchangeConfig;
import se.koc.trader.endpoint.AlertEndpoint;
import se.koc.trader.api.TraderApiEndpoint;
import se.koc.trader.daemon.TraderMarketUpdateManager;
import se.koc.trader.struct.Exchange;
import se.koc.trader.struct.PluginConfig;
import se.koc.trader.api.TraderPage;
import zutil.db.DBConnection;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpServer;
import zutil.net.http.page.HttpFilePage;
import zutil.net.http.page.HttpRedirectPage;
import zutil.plugin.PluginData;
import zutil.plugin.PluginManager;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;


public class TraderServer {
    private static final Logger logger = LogUtil.getLogger();

    private static PluginManager pluginManager;
    private static ScheduledExecutorService daemonExecutor;
    private static HttpServer http;

    private static List<Class<? extends ExchangeConfig>> availableExchangeConfigs = new ArrayList<>();

    public static void main(String[] args) throws SQLException {
        // init logging
        LogUtil.readConfiguration("logging.properties");

        // Init DB and other things
        TraderContext.initialize();

        logger.info("Working directory: " + FileUtil.find(".").getAbsolutePath());

        // init variables
        pluginManager = new PluginManager();
        daemonExecutor = Executors.newScheduledThreadPool(1); // We set only one thread for easier troubleshooting
        http = new HttpServer(TraderContext.getIntegerProperty(TraderContext.PROPERTY_HTTP_PORT));

        DBConnection db = TraderContext.getDB();

        // ------------------------------------
        // Initialize Plugins
        // ------------------------------------

        logger.info("Looking for plugins.");

        // Disable plugins based on settings
        for (PluginData plugin : getAllPlugins()) {
            PluginConfig pluginConfig = PluginConfig.getPluginConfig(db, plugin.getName());

            if (pluginConfig != null && !pluginConfig.isEnabled() && !plugin.getName().equals("Trader-Core")) {
                logger.info("Disabling plugin '" + plugin.getName() + "'.");
                plugin.setEnabled(false);
            }
        }

        // ------------------------------------
        // Initialize Daemons
        // ------------------------------------

        TraderMarketUpdateManager marketUpdateManager = new TraderMarketUpdateManager();
        marketUpdateManager.initialize(daemonExecutor);

        // ------------------------------------
        // Init plugins configurations
        // ------------------------------------

        // Exchange

        for (Iterator<Class<? extends ExchangeConfig>> it = pluginManager.getClassIterator(ExchangeConfig.class); it.hasNext(); ) {
            availableExchangeConfigs.add(it.next());
        }

        // ------------------------------------
        // Init http server
        // ------------------------------------

        logger.info("Initializing HTTP Server.");

        http.setDefaultPage(new HttpFilePage(FileUtil.find(TraderContext.RESOURCE_WEB_ROOT)));
        http.setPage("/", new HttpRedirectPage("/symbol_overview"));
        http.setPage(AlertEndpoint.getInstance().getPath(), AlertEndpoint.getInstance());
        for (Iterator<TraderPage> it = pluginManager.getSingletonIterator(TraderApiEndpoint.class); it.hasNext(); )
            registerPage(it.next());
        for (Iterator<TraderPage> it = pluginManager.getSingletonIterator(TraderPage.class); it.hasNext(); )
            registerPage(it.next());
        http.start();
    }


    public static List<PluginData> getEnabledPlugins() {
        return pluginManager.toArray();
    }

    public static List<PluginData> getAllPlugins() {
        return pluginManager.toArrayAll();
    }


    public static void registerPage(TraderPage page){
        http.setPage(page.getId(), page);
    }


    public static List<Class<? extends ExchangeConfig>> getAvailableExchangeConfigs() {
        return availableExchangeConfigs;
    }
}
