import numpy as np
from classes.TW_Utility import TW_Utility

class TW_Point:
    def __init__(self, X, Y):
        self.X = X
        self.Y = Y

    def getX(self):
        return self.X
    
    def getY(self):
        return self.Y

    def getPoint(self):
        point = []

        if not TW_Utility.is_array(self.X):
            point.append(self.X)
        else:
            for i in range(0, len(self.X)):
                point.append(self.X[i])

        point.append(self.Y)
        return point

class TW_Segment:
    start = None
    end = None
    
    points = []
    regression = None

    TREND_UPWARD = "TREND_UPDARD"
    TREND_DOWNARD = "TREND_DOWNARD"
    TREND_STABLE = "TREND_STABLE"

    CUT_AFTER = "CUT_AFTER"
    CUT_BEFORE = "CUT_BEFORE"

    FIRST_POINT = "FIRST_POINT"
    LAST_POINT = "LAST_POINT"

    def __init__(self, identifier):
        self.start = None
        self.end = None
        self.points = []
        self.regression = None
        self.identifier  = identifier
        self.euclidianDistance = None

    def getIdentifier(self):
        return self.identifier
    
    def getEuclidianDistance(self, pointA, pointB):
        return TW_Utility._euclidianDistance(pointA, pointB)
    
    def getX(self):         
        X = []
        for i in range(0 ,len(self.points)):
            X.append(self.points[i].X)

        return X
    
    def getY(self):
        Y = []
        for i in range(0, len(self.points)):
            Y.append(self.points[i].Y)

        return Y

    def getTrend(self):
        Y = self.getY()
        YMin = Y[0]
        YMax = Y[len(Y) -1]

        diff = ((YMax - YMin) / max(Y)) * 100
        trend = self.TREND_STABLE

        if abs(diff) < 10:
            trend = self.TREND_STABLE
        elif diff < 10:
            trend = self.TREND_DOWNARD
        else:
            trend = self.TREND_UPWARD

        return diff, trend

    def addPoint(self, point: TW_Point):
        self.points.append(point)
        self.end = point

        nbrColumn = TW_Utility.np_number_columns(point.getPoint())
        origin = np.zeros(nbrColumn)
        self.euclidianDistance = self.getEuclidianDistance(origin, point.getPoint())

    @staticmethod
    def rebaseSegmentsFromIndexAndCoordinate(segments, index, diffX, diffY):
        for i in range(index, len(segments)):
            minPoint = None
            maxPoint = None

            for j in range(0, len(segments[i].points)):
                rebasedPoint = segments[i].points[j]
                rebasedPointX = rebasedPoint.getX()
                rebasedPointX = rebasedPointX + diffX
                rebasedPointY = rebasedPoint.getY()
                rebasedPointY = rebasedPointY + diffY
                segments[i].points[j] = TW_Point(rebasedPointX, rebasedPointY)

                if j == 0:
                    minPoint = TW_Point(rebasedPointX, rebasedPointY)
                    segments[i].start = minPoint
                elif j == len(segments[i].points) -1:
                    maxPoint = TW_Point(rebasedPointX, rebasedPointY)
                    segments[i].end = maxPoint

        return segments
            
    @staticmethod
    def rebaseSegmentPoint(segment, diffX, diffY, pointToRebase = FIRST_POINT): 
        if pointToRebase == TW_Segment.FIRST_POINT:
            rebasedPoint = segment.points[0]
            rebasedPointX = rebasedPoint.getX()
            rebasedPointX = rebasedPointX + diffX
            rebasedPointY = rebasedPoint.getY()
            rebasedPointY = rebasedPointY + diffY
            rebasedPoint = TW_Point(rebasedPointX, rebasedPointY)

            segment.points[0] = rebasedPoint
            segment.start = rebasedPoint
        else:
            rebasedPoint = segment.points[len(segment.points) -1]
            rebasedPointX = rebasedPoint.getX()
            rebasedPointX = rebasedPointX + diffX
            rebasedPointY = rebasedPoint.getY()
            rebasedPointY = rebasedPointY + diffY
            rebasedPoint = TW_Point(rebasedPointX, rebasedPointY)

            segment.points[len(segment.points) -1] = rebasedPoint
            segment.end = rebasedPoint
            
        return segment

    @staticmethod
    def cutSegment(segment, intersectionPoint: TW_Point, cutMode = CUT_BEFORE):
        nbrColumn = TW_Utility.np_number_columns(intersectionPoint)
        segmentFirstPointX = np.array(segment.points[0].getX())
        segmentFirstPointY = np.array(segment.points[0].getY())
        segmentLastPointX = np.array(segment.points[len(segment.points) -1].getX())
        segmentLastPointY = np.array(segment.points[len(segment.points) -1].getY())

        if cutMode == segment.CUT_BEFORE:
            segmentLastPointX = intersectionPoint.getX()
            segmentFirstPointY = intersectionPoint.getY()
            segment.points[len(segment.points) -1] = TW_Point(segmentLastPointX, segmentFirstPointY)
        else:
            segmentFirstPointX = intersectionPoint.getX()
            segmentFirstPointY = intersectionPoint.getY()
            segment.points[0] = TW_Point(segmentFirstPointX, segmentFirstPointY)

        return segment