# ---------------------------------------------------------------------------------------------------------------------
"""
Author: Raphael Andreas Elbing
Last Modified: 25/08/2022
License: This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License.
"""
# --------------------------------------------------------------------------------------------------------------------
"""This file serves the purpose to transform the outputs of "monte_carlo_simulations.py into a multi dimensional
data frame called compact_results."""

import pickle
import pandas as pd

proof_of_concept_run = True

# Settings
considered_runs = 10000
start_year = 2015

# set folder path
if proof_of_concept_run:
    folder_path = "monte_carlo_results/proof_of_concept"
    considered_runs = 10

else:
    folder_path = "monte_carlo_results/full_model_8_22_12"

# If an evaluation could not be compleded, one can continue. continue_calculation has to be set to "True"
# The evaluation can be continued every 1000 runs (something like 2398 does not work).
continue_calculation = False
if continue_calculation:
    from_run = 4000
    print("continue run:{}".format(continue_calculation))

    print("From run {}".format(from_run))
else:
    from_run = 0

# loading required data
print('Loading file:')

dict_list = []

if proof_of_concept_run:
    with open("{}/results.pkl".format(folder_path), "rb") as f:
        dict_list.append(pickle.load(f))

else:
    for i in range(0, 10000, 1000):
        print("{}/run_from_{}_till_{}.pkl".format(folder_path, i, i + 999))

        with open("{}/run_from_{}_till_{}.pkl".format(folder_path, i, i + 999), "rb") as f:
            dict_list.append(pickle.load(f))

# Creating one carlo dictionary
monte_carlo_reuse_dic = dict_list.pop(0)

# add other dictionaries
print('Create dictionary:')
while len(dict_list) != 0:
    monte_carlo_reuse_dic.update(dict_list.pop(0))

# # print("Level 1:")
# print(monte_carlo_reuse_dic.keys())
run_names = list(monte_carlo_reuse_dic.keys())

# print("Level 2:")
# print(monte_carlo_reuse_dic["1"].keys())

# print("Level 3")
# print(monte_carlo_reuse_dic["1"]["reuse_data_dic"].keys())
n_years = len(monte_carlo_reuse_dic["1"]["reuse_data_dic"].keys())
row_index = [start_year + i for i in range(n_years)]

# print("Level 4:")
# print(monte_carlo_reuse_dic["1"]["reuse_data_dic"]["1"])

stock_flow_name = monte_carlo_reuse_dic["1"]["reuse_data_dic"]["1"].columns.tolist(
)

item_list_dic = {}
for stock_flow in stock_flow_name:
    item_list_dic[stock_flow] = ["sum"] + monte_carlo_reuse_dic["1"]["reuse_data_dic"][
        "1"
    ][stock_flow].index.tolist()

# get the name of stocks and flows
stock_flow_name = (
        stock_flow_name
        + monte_carlo_reuse_dic["1"]["matrace_data_dic"]["1"].columns.tolist()
)

# create a list with columns
for stock_flow in monte_carlo_reuse_dic["1"]["matrace_data_dic"]["1"].columns.tolist():
    item_list_dic[stock_flow] = ["sum"] + monte_carlo_reuse_dic["1"][
        "matrace_data_dic"
    ]["1"][stock_flow].index.tolist()

# Create structure for a multi index pandas
tuples_list = []

for run in run_names[from_run:(from_run + 1000)]:

    for stock_flow in stock_flow_name:
        for item in item_list_dic[stock_flow]:
            tuples_list.append((run, stock_flow, item))

index_monte_carlo_reuse_results_pd = pd.MultiIndex.from_tuples(
        tuples_list, names=["run", "stock_flow", "item"]
)

monte_carlo_reuse_results_pd = pd.DataFrame(
        {}, index=row_index, columns=index_monte_carlo_reuse_results_pd
)

# set range for data transformation
if continue_calculation:
    run_range = range(from_run, considered_runs)
else:
    run_range = range(considered_runs)

key_level_2 = "reuse_data_dic"
key_level_2_ma = "matrace_data_dic"

print('Start treating data')
for run in run_range:
    if (run + 1) % 1000 or (run + 1) > 100:
        print("run {} of {}".format(run + 1, considered_runs))

    # Reuse part
    for stock_flow in monte_carlo_reuse_dic["1"]["reuse_data_dic"][
        "1"
    ].columns.tolist():
        for item in item_list_dic[stock_flow]:
            for year in range(n_years):

                # Getting the sum
                if item == "sum":

                    monte_carlo_reuse_results_pd[str(run), stock_flow, item].iloc[
                        year
                    ] = monte_carlo_reuse_dic[str(run)][key_level_2][str(year)][
                        stock_flow
                    ].sum()

                # Getting single items
                else:
                    monte_carlo_reuse_results_pd[str(run), stock_flow, item].iloc[
                        year
                    ] = monte_carlo_reuse_dic[str(run)][key_level_2][str(year)][
                        stock_flow
                    ].loc[
                        item
                    ]

    # matrace part
    for stock_flow in monte_carlo_reuse_dic["1"]["matrace_data_dic"][
        "1"
    ].columns.tolist():
        for item in item_list_dic[stock_flow]:
            for year in range(n_years):

                # Getting the sum
                if item == "sum":

                    monte_carlo_reuse_results_pd[str(run), stock_flow, item].iloc[
                        year
                    ] = monte_carlo_reuse_dic[str(run)][key_level_2_ma][str(year)][
                        stock_flow
                    ].sum()

                # Getting single items
                else:
                    monte_carlo_reuse_results_pd[str(run), stock_flow, item].iloc[
                        year
                    ] = monte_carlo_reuse_dic[str(run)][key_level_2_ma][str(year)][
                        stock_flow
                    ].loc[
                        item
                    ]

    if (run + 1) % 1000 == 0:
        with open(
                "{}/compact_results_run_{}_till_{}.pkl".format(
                        folder_path, from_run, run), "wb"
        ) as f:
            pickle.dump(monte_carlo_reuse_results_pd, f)

        # create new table
        from_run = run + 1

        tuples_list = []

        for run in run_names[from_run:(from_run + 1000)]:
            for stock_flow in stock_flow_name:
                for item in item_list_dic[stock_flow]:
                    tuples_list.append((run, stock_flow, item))

        index_monte_carlo_reuse_results_pd = pd.MultiIndex.from_tuples(
                tuples_list, names=["run", "stock_flow", "item"]
        )

        monte_carlo_reuse_results_pd = pd.DataFrame(
                {}, index=row_index, columns=index_monte_carlo_reuse_results_pd)

# Drop backup at end
if proof_of_concept_run:
    with open(
            "{}/compact_results.pkl".format(folder_path), "wb"
    ) as f:
        pickle.dump(monte_carlo_reuse_results_pd, f)

else:
    with open(
            "{}/compact_results_run_{}_final.pkl".format(folder_path, run + 1), "wb"
    ) as f:
        pickle.dump(monte_carlo_reuse_results_pd, f)

print('Compact results are stored.')
