# naive forecast strategies for the power usage dataset
from math import sqrt
from numpy import split
from numpy import array
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from matplotlib import pyplot
import datetime

# split a univariate dataset into train/test sets
def split_dataset(data):
    # split into standard weeks
    train, test = data[6:-93], data[-93:-2]
    # restructure into windows of weekly data
    train = array(split(train, len(train)/7))
    test = array(split(test, len(test)/7))
    return train, test

# evaluate one or more weekly forecasts against expected values
def evaluate_forecasts(actual, predicted):
    print("actual = ",actual)
    print("predicted = ", predicted)
    scores = list()
    # calculate an RMSE score for each day
    for i in range(actual.shape[1]):
        # calculate mse
        mse = mean_squared_error(actual[:, i], predicted[:, i])
        # calculate rmse
        rmse = sqrt(mse)
        # store
        scores.append(rmse)
    # calculate overall RMSE
    s = 0
    for row in range(actual.shape[0]):
        for col in range(actual.shape[1]):
            s += (actual[row, col] - predicted[row, col])**2
    score = sqrt(s / (actual.shape[0] * actual.shape[1]))
    return score, scores

# summarize scores
def summarize_scores(name, score, scores):
    s_scores = ', '.join(['%.1f' % s for s in scores])
    print('%s: [%.3f] %s' % (name, score, s_scores))

# evaluate a single model
def evaluate_model(model_func, train, test):
    variabletopredict = 4
    # history is a list of weekly data
    history = [x for x in train]
    # walk-forward validation over each week
    predictions = list()
    for i in range(len(test)):
        # predict the week
        yhat_sequence = model_func(history)
        # store the predictions
        predictions.append(yhat_sequence)
        # get real observation and add to history for predicting the next week
        history.append(test[i, :])
    predictions = array(predictions)
    # evaluate predictions days for each week
    #score, scores = evaluate_forecasts(test[:, :, 0], predictions)
    score, scores = evaluate_forecasts(test[:, :, variabletopredict], predictions)
    return score, scores

# daily persistence model
def daily_persistence(history):
    variabletopredict = 4
    # get the data for the prior week
    last_week = history[-1]
    #print("last_week = ",last_week)
    # get the total active power for the last day
    #value = last_week[-1, 0]
    value = last_week[-1, variabletopredict]
    #print("value = ", value)
    # prepare 7 day forecast
    forecast = [value for _ in range(7)]
    #print("forecast = ", forecast)
    return forecast

# weekly persistence model
def weekly_persistence(history):
    variabletopredict = 4
    # get the data for the prior week
    last_week = history[-1]
    #print("last_week = ", last_week)
    # print("forecast = ", last_week[:, 0])
    # return last_week[:, 0]
    #print("forecast = ", last_week[:, variabletopredict])
    return last_week[:, variabletopredict]

starttime = datetime.datetime.now()
# load the new file
dataset = read_csv('airstation_days_f69794578a00922ea1804a2e87093fb5.csv', header=0,
infer_datetime_format=True, parse_dates=['datetime'], index_col=['datetime'])
# split into train and test
train, test = split_dataset(dataset.values)
# define the names and functions for the models we wish to evaluate
models = dict()
models['daily'] = daily_persistence
models['weekly'] = weekly_persistence
# evaluate each model
days = ['sun', 'mon', 'tue', 'wed', 'thr', 'fri', 'sat']
for name, func in models.items():
    # evaluate and get scores
    score, scores = evaluate_model(func, train, test)
    # summarize scores
    summarize_scores(name, score, scores)
    # plot scores
    pyplot.plot(days, scores, marker='o', label=name)
# show plot
pyplot.legend()
pyplot.show()
endtime = datetime.datetime.now()
elapsedtime = endtime - starttime
print("starttime = ", starttime)
print("endtime = ", endtime)
print("elapsedtime = ", elapsedtime)