import numpy as np
from sklearn.model_selection import StratifiedKFold
import matplotlib.pyplot as plt
import pandas as pd

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split

from classes.TW_Utility import TW_Utility
from classes.TW_Dataset_Helper import TW_Dataset_Helper
from classes.TW_Segment import TW_Point, TW_Segment
from classes.TW_Segment_Regressor import TW_Segment_Regressor
from classes.TW_Linear_regression_old import TW_2D_Linear_regression
from classes.TW_Matrice import TW_Matrice

from classes.TW_MultipleSegment_Regressor import TW_MultipleSegment_Regressor
from classes.TW_Object_Type_Validator import TW_Object_Type_Validator, TW_Object_Type_Validation

#https://docs.pytest.org/en/stable/

test = [[53.25,33,19,52.6]]
toto = test[::-1]


X = np.array([[10,20], [30,40], [60,20], [92,120], [140,80]])
Y = np.array([10, 20, 30, 40, 50])
multipleSegmentRegressor = TW_MultipleSegment_Regressor('test2D')
multipleSegmentRegressor.processDataset(X,Y)

XMinus1 = np.array([[10,20], [30,40], [60,20], [92,120], [140,80]])
#YMinus1 = np.array([10, 25, 28, 56, 32])
YMinus1 = np.array([10, 20, 30, 40, 50])
multipleSegmentRegressorPreviousYear = TW_MultipleSegment_Regressor('test2D1YearAgo')
multipleSegmentRegressorPreviousYear.processDataset(XMinus1, YMinus1)

forecastedSegments, forecastedValuesX, forecastedValuesY = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressorPreviousYear, [[140,80]], [[200,120]])

'''
X = np.array([[10,20], [30,40], [60,20], [92,120]])
Y = np.array([10, 20, 30, 40])
multipleSegmentRegressor = TW_MultipleSegment_Regressor('test2D')
multipleSegmentRegressor.processDataset(X,Y)

XMinus1 = np.array([[10,20], [30,40], [60,20], [92,120]])
YMinus1 = np.array([10, 25, 28, 56])
multipleSegmentRegressorPreviousYear = TW_MultipleSegment_Regressor('test2D1YearAgo')
multipleSegmentRegressorPreviousYear.processDataset(XMinus1, YMinus1)

forecastedSegments = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressorPreviousYear, [[140,80]], [[200,120]])
'''


multipleSegmentRegressor.showGraphics(
    multipleSegmentRegressor.currentRegressor.segments,
    forecastedSegments
)

unserialzedRegressor = TW_MultipleSegment_Regressor.unserialize('test.pkl')
unserialzedRegressor.showGraphics(multipleSegmentRegressor.currentRegressor.segments)

XMinus1 = np.array([1,2,3,4,5])
YMinus1 = np.array([10,30,45,85,300])

X = np.array([1,2,3,4,5])
Y = np.array([10,20,65,45,55])

multipleSegmentRegressor1YearAgo = TW_MultipleSegment_Regressor()
segmentRegressor1YearAgo = multipleSegmentRegressor1YearAgo.processDataset(XMinus1,YMinus1)

multipleSegmentRegressor = TW_MultipleSegment_Regressor()
multipleSegmentRegressor.processDataset(X,Y)
predictedSegments, predictedValuesX, predictedValuesY = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressor1YearAgo, 5, 8)
multipleSegmentRegressor.showGraphics(multipleSegmentRegressor.currentRegressor.segments, predictedSegments)

toto = "lolo"

'''

#a faire
#le regresseur ne sait pas dépasser le graphique
#prévoir un traitement des outliers en se basant sur la distribution du graphique
multipleSegmentRegressor1YearAgo = TW_MultipleSegment_Regressor()
segmentRegressor1YearAgo = multipleSegmentRegressor1YearAgo.processDataset(XMinus1,YMinus1)

multipleSegmentRegressor = TW_MultipleSegment_Regressor()
segmentRegressor = multipleSegmentRegressor.processDataset(X,Y)

#predictedSegments = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressor1YearAgo, [[35,43]])
predictedSegments = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressor1YearAgo, 6, 10)
multipleSegmentRegressor.showGraphics(segmentRegressor.segments, predictedSegments)


'''
data = np.array([[1.2, 2.3], [2.1, 3.4], [3.3, 1.8]])
histogram, edges = np.histogramdd([[1.2, 2.3], [2.1, 3.4], [3.3, 1.8], [3.3, 1.8]], bins=[2,2,2,2])
histogram, edges = np.histogramdd([[1.2, 2.3], [2.1, 3.4], [3.3, 1.8], [5, 7], [9,3]], bins=2)
'''



'''
test = np.digitize(Y, [20,40,80])

X,Y = TW_Dataset_Helper.removeOutlier(X,Y)
toto = "lolo"
'''

'''
X = np.array([-10, 0.2, 2.6, 6.4, 12, 10])
bins = np.array([0, 1.0, 2.5, 4.0, 10.0])
test = np.digitize(X, bins, right=True)

X = np.array([[10,20], [30,40], [60,20], [92,60], [140,80], [180,100]])
Y = np.array([10, 20, 30, 40, 50, 60])
'''


'''
hist, edges = np.histogramdd(Y, bins=len(Y))
hist = np.sum(hist, axis=0)

XY = np.array([[10,20,10], [30,40,20], [60,80,30], [92,93,40], [140,150,50], [180,210,60]])
hist, edges = np.histogramdd(XY, bins=10)
lolo = np.digitize(XY, edges)
'''

X = np.array([10, 30, 60, 92, 130, 150, 160])
Y = np.array([10, 20, 20, 25, 50, 79, 800])
X, Y = TW_Dataset_Helper.removeOutlier(X,Y)

regressor = TW_MultipleSegment_Regressor()
TW_MultipleSegment_Regressor.processDataset()
X = np.array([[10,20], [30,40], [60,20], [92,60], [140,80], [180,100]])
Y = np.array([10, 20, 10, 40, 50, 600])
joined = TW_Dataset_Helper.mergeAlongFirstAxis(X,Y)
hist, edges = np.histogramdd(joined, 6)
res = np.digitize(Y, edges[2])


print(Y)
print(edges[2])
print(res)

#np.append(X,Y,axis=1)
newarr = np.hstack((X,Y))

X,Y = TW_Dataset_Helper.removeOutlier(X,Y)
toto = "lolo"

'''
test = TW_Utility.get_middle_point([1,3],[7,8])
'''

#test2 = TW_Utility._euclidianDistance([1,3], [7,8])

'''
test2 = TW_Utility._euclidianDistance([1,3, 15], [7,8, 35])
test2 = TW_Utility._euclidianDistance([[1,3], 2], [[7,8], 3])
'''

'''
p1 = [1,3, 2]
p2 = [7,8, 3]
p3 = [2,4, 2]
p4 = [1,5, 3]

TW_Utility.intersect_segments_2d(p1, p2, p3, p4)
'''

# Exemple de données : 2 variables explicatives
X = np.array([
    [1, 2],
    [2, 0],
])
y = np.array([2, 1])


X = np.array([0, 1, 2, 3, 4, 5])

#X = np.array([[1,2],[4,5],[7,8]])

'''
X = np.array([[3,4],[5,6],[8,9]])
Y = np.array([3,6,9])
'''

'''
multipleSegmentRegressor = TW_MultipleSegment_Regressor()
segmentRegressor = multipleSegmentRegressor.processDataset(X,Y)
predictedValue = segmentRegressor.predict([1,2])
'''

'''
X = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
Y = np.array([10,20,35,45,55,90,92,93,105,115,125,145,165,185,205,225,285,292,350,104])


dataSetHelper = TW_Dataset_Helper()
canSplit, splittedX_Train, splittedX_Test, splittedY_Train, splittedY_Test = dataSetHelper.split(2, X, Y, maxdiff=False)

multipleSegmentRegressor = TW_MultipleSegment_Regressor()
if canSplit == True:
    segmentRegressor = multipleSegmentRegressor.procesSplitedDataset(splittedX_Train, splittedY_Train)
else:
    segmentRegressor = multipleSegmentRegressor.processDataset(X,Y)
'''


# Define custom bins and ranges for each dimension
histogram, edges = np.histogramdd(
    data,
    bins=[3, 4, 5],  # 3 bins for x, 4 for y, 5 for z
    range=[[0, 1], [0, 1], [0, 1]]  # Ranges for each dimension
)

data2 = [[1.2, 2.3], [2.1, 3.4], [3.3, 1.8], [10, 10], [30,30], [40,40]]
histogram2, edges2 = np.histogramdd(data2, bins=[[0,1]])

print(histogram2)
print(edges2)
'''
condensedTable = [
    [10,20,10],
    [30,40,20],
    [60,80,30],
    [92,93,40],
    [140,150,50],
    [200,210,60]
]
'''
condensedTable = [
    [10,20],
    [30,40],
    [60,80],
    [92,93],
    [140,150],
    [200,210]
]
H, edges = np.histogramdd(condensedTable, [2,2])


matchedIndex = TW_Dataset_Helper._closestIndexWithinPopulation(Y, 37, 'MAX')

standardDeviation = np.std(Y)
hist, xEdges, yEdges = np.histogram2d(X, Y)

print(yEdges)
print(np.sum(hist, axis=0))

XMinus1 = np.array([1,2,3,4,5,6,7,8])
YMinus1 = np.array([10,30,45,55,65,20,10,60])
'''


X = np.array([[10,20], [30,40], [60,80], [92,93], [140,150], [200,210]])
Y = np.array([10, 20, 30, 40, 50, 60])
hist, xEdges, yEdges = np.histogram2d(X, Y)


'''
X = np.array([[3,4],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15]])
Y = np.array([10,20,35,45,55,20,70])

XMinus1 = np.array([[3,4],[4,5],[6,7],[8,9],[18,20],[22,22],[23,24]])
YMinus1 = np.array([10,30,45,65,20,10,60])
'''

#a faire
#le regresseur ne sait pas dépasser le graphique
#prévoir un traitement des outliers en se basant sur la distribution du graphique
multipleSegmentRegressor1YearAgo = TW_MultipleSegment_Regressor()
segmentRegressor1YearAgo = multipleSegmentRegressor1YearAgo.processDataset(XMinus1,YMinus1)

multipleSegmentRegressor = TW_MultipleSegment_Regressor()
segmentRegressor = multipleSegmentRegressor.processDataset(X,Y)

#predictedSegments = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressor1YearAgo, [[35,43]])
predictedSegments, predictedValuesX, predictedValuesY = multipleSegmentRegressor.predictUsingHistoricalData(multipleSegmentRegressor1YearAgo, 6, 10)
multipleSegmentRegressor.showGraphics(segmentRegressor.segments, predictedSegments)
'''
X = np.array([[10,20], [30,40], [60,80], [92,93], [140,150], [200,210]])
Y = np.array([10, 20, 30, 40, 50, 60])

multipleSegmentRegressor = TW_MultipleSegment_Regressor()
segmentRegressor = multipleSegmentRegressor.processDataset(X,Y)
predictedValue = segmentRegressor.predict([[85,88],[92,97]])
'''

'''
reg = LinearRegression().fit(X,Y)
reg.predict(3)
'''

# Prédire un plan pour une grille de points
x1_range = np.linspace(X[:, 0].min(), X[:, 0].max(), 10)
x2_range = np.linspace(X[:, 1].min(), X[:, 1].max(), 10)
x1_grid, x2_grid = np.meshgrid(x1_range, x2_range)
X_grid = np.c_[x1_grid.ravel(), x2_grid.ravel()]
y_grid = model.predict(X_grid)
y_grid = y_grid.reshape(x1_grid.shape)


# Affichage 3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:, 0], X[:, 1], y, color='blue', label='Données')
ax.plot_surface(x1_grid, x2_grid, y_grid, color='red', alpha=0.5, label='Plan de régression')

ax.set_xlabel('X1')
ax.set_ylabel('X2')
ax.set_zlabel('y')
ax.set_title('Régression linéaire (plan)')
plt.show()








'''
x = np.array([0, 1, 2, 3, 4, 5])
y = np.array([2, 3, 5, 7, 11, 13])

matrice = TW_Matrice()
solutions, constants = matrice.gaussian_system_linear_equation(x, y)
'''

'''
predictedValue = segmentRegressor.predict(6)

# todo il faut trouver le segment le plus proche si il n'existe pas
# a récupération de la valeur du segment pour un dataset multidimensionnel
#a tester dataset splitté


segmentRegressor.showGraphics()
toto = "lolo"
'''