import numpy as np
import pandas as pd
from sklearn import svm, ensemble
from xgboost import XGBRegressor
from sklearn.preprocessing import StandardScaler


class MLMethods:
    def __init__(self, path):
        self.path = path
        self.train_size = 1095  # index to 2014.1.1
        self.svr = svm.SVR(degree=2, C=0.1, epsilon=0.6)  # degree=2, C=0.1, epsilon=0.6
        self.gbrt = ensemble.GradientBoostingRegressor(n_estimators=10, learning_rate=0.5, max_depth=1) #n_estimators=10, learning_rate=0.5, max_depth=1
        self.xgboost = XGBRegressor()
        self.wd_scaler, self.mint_scaler, self.maxt_scaler = StandardScaler(), StandardScaler(), StandardScaler()
        self._data_loader()

    def _data_loader(self):
        data = pd.read_csv(self.path)
        wd = self.wd_scaler.fit_transform(np.array(data['WD']).reshape(-1, 1))
        mint = self.mint_scaler.fit_transform(np.array(data['MinT']).reshape(-1, 1))
        maxt = self.maxt_scaler.fit_transform(np.array(data['MaxT']).reshape(-1, 1))

        x_data = np.empty((len(wd)-1, 2))
        y_data = np.empty(len(wd)-1)

        for i in range(len(wd) - 1):
            x_data[i, 0] = mint[i + 1]
            x_data[i, 1] = maxt[i + 1]
            # x_data[i, 2] = wd[i]
            y_data[i] = wd[i + 1]

        # seperate dataset
        self.x_train = x_data[:self.train_size, :]
        self.y_train = y_data[:self.train_size].reshape(-1, 1)
        self.x_test = x_data[self.train_size:, :]
        self.y_test = y_data[self.train_size:].reshape(-1, 1)
        # print(self.x_train, self.x_test)
        # print(self.y_train, self.y_test)
        # print(x_data, y_data)

    def fit(self):
        self.svr.fit(self.x_train, self.y_train)
        self.gbrt.fit(self.x_train, self.y_train)
        self.xgboost.fit(self.x_train, self.y_train)

    def predict(self):
        self.svr_pred = self.svr.predict(self.x_test)
        self.gbrt_pred = self.gbrt.predict(self.x_test)
        self.xgboost_pred = self.xgboost.predict(self.x_test)

        self.svr_pred = self.wd_scaler.inverse_transform(self.svr_pred.reshape(-1, 1))
        self.gbrt_pred = self.wd_scaler.inverse_transform(self.gbrt_pred.reshape(-1, 1))
        self.xgboost_pred = self.wd_scaler.inverse_transform(self.xgboost_pred.reshape(-1, 1))
        return self.svr_pred, self.gbrt_pred, self.xgboost_pred

    def acquire_ground_truth(self):
        return self.wd_scaler.inverse_transform(self.y_test.reshape(-1, 1))

if __name__ == '__main__':
    pass