import dash
from dash import html, dcc, Input, Output
import dash_bootstrap_components as dbc
import webbrowser
from threading import Timer
from pathlib import Path
import pandas as pd
from Toolbox.classes.InputManager import import_pkl_data, import_formip_data, download_input_data
from Toolbox.classes.ProcessManager import DataProcessor
from Toolbox.pages.overview_db import OverviewDB
from Toolbox.pages.forest_db import ForestDB
from Toolbox.pages.price_db import PriceDB
from Toolbox.pages.bitrade_db import BiTradeDB
from Toolbox.pages.validation_db import ValidationDB
from Toolbox.pages.worldmap_db import WorldMapDB
from Toolbox.classes.utils import PlotUtils
import Toolbox.parameters.default_parameters as dp
from Toolbox.parameters.paths import PACKAGEDIR,SCINPUTPATH,AIINPUTPATH,SCFOLDERPATH
import warnings


class timba_dashboard:

    def __init__(self,
                 FOLDER_PATH: Path = PACKAGEDIR,
                 num_files_to_read: int = 10,
                 print_settings: bool = False):

        self.num_files_to_read = num_files_to_read
        self.SCENARIO_PATH = FOLDER_PATH / SCFOLDERPATH / SCINPUTPATH
        self.ADDINFO_PATH = FOLDER_PATH / SCFOLDERPATH / AIINPUTPATH
        self.FOLDER_PATH = FOLDER_PATH
        self.print_settings = print_settings
        self.app = None
        self.data = None
        self.formip_data = None

    def create_app(self):
        self._app_initial()
        self._import_data()
        self._import_formip()
        self._build_layout()
        self._register_callbacks()
        return self.app
    
    def run(self, open_browser=True, port=8053):
        self.create_app()

        if open_browser:
            Timer(1, lambda: webbrowser.open_new(f"http://localhost:{port}")).start()

        self.app.run(
            host="localhost",
            port=port,
            debug=False,
            dev_tools_ui=False,
            dev_tools_hot_reload=False
        )

    def _app_initial(self):
        self.app = dash.Dash(
            __name__,
            use_pages=False,
            external_stylesheets=[dbc.themes.BOOTSTRAP]
        )
        self.app.title = "TiMBA Dashboards"
        self.app.config.suppress_callback_exceptions = True

    def _import_data(self):
        warnings.simplefilter(action='ignore', category=FutureWarning)

        if not (self.SCENARIO_PATH.exists() and self.ADDINFO_PATH.exists()):
            print(f"No data found at: {self.FOLDER_PATH}")
            print("\nStart input data download:")
            download = download_input_data(SCENARIO_FOLDER_PATH=self.SCENARIO_PATH,
                                           ADDINFOPATH=self.ADDINFO_PATH)
            download.download_data_from_github()

        print("\nStart the read-in process of TiMBA data")
        importer = import_pkl_data(
            num_files_to_read=self.num_files_to_read,
            SCENARIOPATH=self.SCENARIO_PATH,
            ADDINFOPATH=self.ADDINFO_PATH
        )

        data, country_data, commodity_data, hist_data = importer.main()
        # data_small={}
        # data_small[dp.overview_db] = data[dp.overview_db].head(20)
        # data_small[dp.forest_db] = data[dp.forest_db].head(20)
        # country_small = country_data.head(5)
        # commodity_small = commodity_data.head(5)
        # hist_small = hist_data.head(20)
        # data_small[dp.overview_db].to_pickle("tests/test_data/data_overview.pkl")
        # data_small[dp.forest_db].to_pickle("tests/test_data/data_forest.pkl")
        # country_small.to_pickle("tests/test_data/country.pkl")
        # commodity_small.to_pickle("tests/test_data/commodity.pkl")
        # hist_small.to_pickle("tests/test_data/hist.pkl")
        
        process = DataProcessor(
            data=data,country_data=country_data,
            commodity_data=commodity_data,
            data_hist=hist_data
        )

        self.data = process.combined_data()
        self.pivot_map_data = process.pivot_map_data()
        self.pivot_df_stock, self.pivot_df_area = process.pivot_map_forest_data()
        # self.data[dp.overview_db].to_pickle("data_overview.pkl")
        # self.data[dp.forest_db].to_pickle("data_forest.pkl")
        # self.pivot_map_data.to_pickle("pivot_map_data.pkl")
        # self.pivot_df_stock.to_pickle("pivot_df_stock.pkl")
        # self.pivot_df_area.to_pickle("pivot_df_area.pkl")
        print("TiMBA data is fully loaded!\n")

    def _import_formip(self):
        importer = import_formip_data(
            timba_data=self.data,
            only_baseline_sc=True,
            ADDINFOPATH=self.ADDINFO_PATH
        )
        self.formip_data = importer.load_formip_data()

    def _build_layout(self):
        self.scenarios = sorted(self.data[dp.overview_db]["Scenario"].dropna().unique())
        colors = PlotUtils().get_scenario_colors(self.scenarios)

        self.overview_db = OverviewDB(
            app=self.app,
            data=self.data,
            colors=colors
            #print_settings=self.print_settings,
        )
        self.forest_db = ForestDB(
            app=self.app,
            data=self.data[dp.forest_db],
            colors=colors
            #print_settings=self.print_settings,
        )
        self.price_db = PriceDB(
            app=self.app,
            data=self.data[dp.overview_db],
            colors=colors
            #print_settings=self.print_settings,
        )
        self.bitrade_db = BiTradeDB(
            app=self.app,
            data=self.data[dp.overview_db],
            colors=colors
            #print_settings=self.print_settings,
        )
        self.validation_db = ValidationDB(
            app=self.app, 
            data=self.formip_data
        )
        self.worldmap_db = WorldMapDB(
            app=self.app,
            data=self.pivot_map_data,
            df_stock=self.pivot_df_stock,
            df_area=self.pivot_df_area,
        )

        self.app.layout = html.Div([
            dcc.Location(id="url"),
            dbc.Navbar(
                dbc.Container(
                    dbc.Col(
                        [
                            dbc.NavbarBrand(
                                html.Img(
                                    src=dp.logo,
                                    height="80px",
                                    style={"mixBlendMode": "multiply"}
                                ),
                                className="mx-auto"
                            ),
                            dbc.Nav(
                                [
                                    dbc.NavLink("Overview", href="/", active="exact"),
                                    dbc.NavLink("Forest", href="/forest", active="exact"),
                                    dbc.NavLink("Price", href="/price", active="exact"),
                                    dbc.NavLink("Trade", href="/bitrade", active="exact"),
                                    dbc.NavLink("Validation", href="/validation", active="exact"),
                                    dbc.NavLink("Worldmap", href="/worldmap", active="exact")
                                ],
                                navbar=True,
                                className="tabs-equal justify-content-center mt-2"
                            )
                        ],
                        width=12,
                        className="d-flex flex-column align-items-center"
                    )
                ),
                color=dp.background_color,
                dark=False,
                className="mb-0 border-1 rounded-2 shadow-sm",
                style={"height": "135px"} 
            ),
            html.Div(id="page-content"),
        ])


    def _register_callbacks(self):

        @self.app.callback(
            Output("page-content", "children"),
            Input("url", "pathname")
        )
        def _display_page(pathname):
            if pathname == "/forest":
                return self.forest_db.app_layout
            elif pathname == "/price":
                return self.price_db.app_layout
            elif pathname == "/bitrade":
                return self.bitrade_db.app_layout
            elif pathname == "/validation":
                return self.validation_db.app_layout
            elif pathname == "/worldmap":
                return self.worldmap_db.app_layout
            return self.overview_db.app_layout


if __name__ == "__main__":
    timba_dashboard().run()
