from __future__ import division
import tensorflow as tf
from os import path
import numpy as np
import pandas as pd
import csv
from sklearn.model_selection import StratifiedShuffleSplit
from time import time
from matplotlib import pyplot as plt
import seaborn as sns
from mylibs.jupyter_notebook_helper import show_graph
from tensorflow.contrib import rnn
from tensorflow.contrib import learn
import shutil
from tensorflow.contrib.learn.python.learn import learn_runner
from IPython.display import Image
from IPython.core.display import HTML
from mylibs.tf_helper import getDefaultGPUconfig
from data_providers.binary_shifter_varlen_data_provider import \
    BinaryShifterVarLenDataProvider
from data_providers.price_history_varlen_data_provider import PriceHistoryVarLenDataProvider
from models.model_05_price_history_rnn_varlen import PriceHistoryRnnVarlen
from sklearn.metrics import r2_score
from mylibs.py_helper import factors
from fastdtw import fastdtw
from scipy.spatial.distance import euclidean
from statsmodels.tsa.stattools import coint

dtype = tf.float32
seed = 16011984
random_state = np.random.RandomState(seed=seed)
config = getDefaultGPUconfig()
%matplotlib inline

from common import get_or_run_nn

"""
Explanation: https://r2rt.com/recurrent-neural-networks-in-tensorflow-iii-variable-length-sequences.html
End of explanation
"""


num_epochs = 10
series_max_len = 60
num_features = 1  #just one here, the function we are predicting is one-dimensional
state_size = 400
target_len = 30
batch_size = 47

"""
Explanation: Step 0 - hyperparams
End of explanation
"""


csv_in = '../price_history_03a_fixed_width.csv'
npz_path = '../price_history_03_dp_60to30_from_fixed_len.npz'

# XX, YY, sequence_lens, seq_mask = PriceHistoryVarLenDataProvider.createAndSaveDataset(
#     csv_in=csv_in,
#     npz_out=npz_path,
#     input_seq_len=60, target_seq_len=30)
# XX.shape, YY.shape, sequence_lens.shape, seq_mask.shape

dp = PriceHistoryVarLenDataProvider(filteringSeqLens = lambda xx : xx >= target_len,
                                    npz_path=npz_path)
dp.inputs.shape, dp.targets.shape, dp.sequence_lengths.shape, dp.sequence_masks.shape

"""
Explanation: Step 1 - collect data (and/or generate them)
End of explanation
"""


model = PriceHistoryRnnVarlen(rng=random_state, dtype=dtype, config=config)

graph = model.getGraph(batch_size=batch_size, state_size=state_size,
                       target_len=target_len, series_max_len=series_max_len)

show_graph(graph)

"""
Explanation: Step 2 - Build model
End of explanation
"""


num_epochs, state_size, batch_size

def experiment():
    dynStats, predictions_dict = model.run(epochs=num_epochs,
                                        state_size=state_size,
                                         series_max_len=series_max_len,
                                         target_len=target_len,
                                         npz_path=npz_path,
                                         batch_size=batch_size)
    return dynStats, predictions_dict

from os.path import isdir
data_folder = '../../../../Dropbox/data'
assert isdir(data_folder)

dyn_stats, preds_dict = get_or_run_nn(experiment,
                                      filename='001_plain_rnn_60to30', nn_runs_folder= data_folder + '/nn_runs')

dyn_stats.plotStats()
plt.show()

r2_scores = [r2_score(y_true=dp.targets[ind], y_pred=preds_dict[ind])
            for ind in range(len(dp.targets))]

ind = np.argmin(r2_scores)
ind

sns.tsplot(data=dp.inputs[ind].flatten())

reals = dp.targets[ind]
preds = preds_dict[ind]

r2_score(y_true=reals, y_pred=preds)

fig = plt.figure(figsize=(15,6))
plt.plot(reals, 'b')
plt.plot(preds, 'g')
plt.legend(['reals','preds'])
plt.show()

%%time
dtw_scores = [fastdtw(dp.targets[ind], preds_dict[ind])[0]
             for ind in range(len(dp.targets))]

np.mean(dtw_scores)

coint(preds, reals)

"""
Explanation: Step 3 training the network
End of explanation
"""


num_epochs, state_size, batch_size
cost_func = PriceHistoryRnnVarlen.COST_FUNCS.MSE

def experiment():
    dynStats, predictions_dict = model.run(epochs=num_epochs,
                                           cost_func= cost_func,
                                           state_size=state_size,
                                           series_max_len=series_max_len,
                                           target_len=target_len,
                                           npz_path=npz_path,
                                           batch_size=batch_size)
    return dynStats, predictions_dict

dyn_stats, preds_dict = get_or_run_nn(experiment,
                                      filename='001_plain_rnn_60to30_mse')

dyn_stats.plotStats()
plt.show()

r2_scores = [r2_score(y_true=dp.targets[ind], y_pred=preds_dict[ind])
            for ind in range(len(dp.targets))]

ind = np.argmin(r2_scores)
ind

reals = dp.targets[ind]
preds = preds_dict[ind]

r2_score(y_true=reals, y_pred=preds)

sns.tsplot(data=dp.inputs[ind].flatten())

fig = plt.figure(figsize=(15,6))
plt.plot(reals, 'b')
plt.plot(preds, 'g')
plt.legend(['reals','preds'])
plt.show()

%%time
dtw_scores = [fastdtw(dp.targets[ind], preds_dict[ind])[0]
             for ind in range(len(dp.targets))]

np.mean(dtw_scores)

coint(preds, reals)

"""
Explanation: TODO Co integration
https://en.wikipedia.org/wiki/Cointegration
https://www.quora.com/What-are-some-methods-to-check-similarities-between-two-time-series-data-sets
https://stackoverflow.com/questions/11362943/efficient-cointegration-test-in-python
Mean Squared Error (instead of huber loss)
End of explanation
"""


