"""
Experiment 2.
Comparison of quality for five trainings of the same model with the same configuration
using 10y dataset for training, predicting 200 days from validation period
"""

from src.constants import *
from src.stock import Stock
from src.model import Model
from src.helper import *
import seaborn as sns
import cairosvg

# get stock prices and create a dataframe
stock = Stock('MSFT', START, END, FORCE_FETCH_STOCK)
stock.fetch()

# get dataset
training_validation_dataset = stock.df['Adj Close']
# validation period
TESTING_START = datetime.datetime(2018, 1, 1)
TESTING_END = datetime.datetime(2019, 1, 15)

# get testing data
stock_test = Stock('MSFT', TESTING_START, TESTING_END, FORCE_FETCH_STOCK)
stock_test.fetch()
test_closing_prices = stock_test.df['Adj Close']

# save original prices for later
original_prices = test_closing_prices

# split training validation
training_size = int(len(training_validation_dataset) * TRAIN_VALIDATION_SPLIT)

# normalize data with Z-score
mean = training_validation_dataset[:training_size].mean()
std = training_validation_dataset[:training_size].std()
closing_prices = (training_validation_dataset - mean) / std
test_closing_prices = (test_closing_prices - mean) / std

# prepare datasets for model
train_x, train_y = prepare_dataset_single_model(closing_prices, 0, training_size)
validation_x, validation_y = prepare_dataset_single_model(closing_prices, training_size, None)
testing_x, testing_y = prepare_dataset_single_model(test_closing_prices, 0, None)

# create datasets
training_dataset, validation_dataset = create_datasets(train_x, train_y, validation_x, validation_y, closing_prices.size)

# store data
data = pd.DataFrame()
# put reference prices into dataframe
original_prices_dataframe = pd.DataFrame(
    {'price_prediction': original_prices[60:], 'type': 'referenčná', 'index': np.arange(1, 201)})
data = data.append(original_prices_dataframe)

# create five models
for model_id in range(1, 6):
    # create params
    model_params = ModelParameters(training_dataset, validation_dataset, False, str(model_id) + '-msft-random-trainings', 'models/exp-1-2/', [20, 0])
    # init params
    model = Model(model_params)
    # predict 200 days
    predictions = model.predict(testing_x)
    # reshape to 1d array
    predictions = predictions.reshape(-1)
    # denormalize predictions
    scaled_predictions = np.array(predictions) * std + mean

    # store model
    if not model.stored():
        model.save()

    # put predictions into dataframe
    predictions_dataframe = pd.DataFrame(
        {'price_prediction': scaled_predictions, 'type': str(model_id) + '# predikovaná', 'index': np.arange(1, 201)})
    data = data.append(predictions_dataframe)

data = data.reset_index()
# create visualisation from trained models
# set sns default theme
sns.set(style='whitegrid', palette='tab10')
# plot data
facet_grid = sns.relplot(data=data,
                         x="index",
                         y="price_prediction", hue="type",
                         kind="line",
                         facet_kws=dict(sharex=False, sharey=False),
                         legend=False, height=height, aspect=aspect, errorbar=None)

# set labels, titles and legend
facet_grid.set_axis_labels("Predikované dni", "Cena akcie ($)", labelpad=15, size=font_size + 4)
facet_grid.figure.legend(title='Cena akcie',
                         labels=['Reálna', 'Predikovaná - model 1', 'Predikovaná - model 2', 'Predikovaná - model 3', 'Predikovaná - model 4', 'Predikovaná - model 5'],
                         title_fontsize=title_font_size,
                         fontsize=font_size + 2, loc='upper right',
                         bbox_to_anchor=bbox_to_anchor, borderaxespad=1)

# save graph
plt.suptitle('Predikcie 200 dní z validačného obdobia (2018≈2019)', fontsize=24)
plt.tight_layout(pad=3, rect=[0, 0, 0.80, 1])
file_name = 'experiment-results/exp-1-2/experiment-2-random-trainings'
plt.savefig(file_name + '.svg', format='svg')
cairosvg.svg2pdf(url=file_name + '.svg', write_to=file_name + '.pdf')
plt.show()
