import os
import re

from dcm_reader.exceptions import LineWithWrongIDsException


class Line:

    def __init__(self, point0, point1, line_id, SOPInstanceUID):
        self.x0, self.y0 = self._parse_point(point0)
        self.x1, self.y1 = self._parse_point(point1)
        self.line_id = line_id
        self.SOPInstanceUID = SOPInstanceUID

    def _parse_point(self, point):
        values = point.split(", ")
        x = float(values[0])
        y = float(values[1])
        return x, y

    def get_point0(self):
        return self.x0, self.y0

    def get_point1(self):
        return self.x1, self.y1

    def __repr__(self):
        return "(line_id = {}; x0 = {}, y0 = {}; x1 = {}, y1 = {})".format(self.line_id, self.x0, self.y0, self.x1,
                                                                           self.y1)


class MeningeomaMeasurement:

    def __init__(self, line1: Line, line2: Line):
        self.line1 = line1
        self.line2 = line2
        self.SOPInstanceUID = line1.SOPInstanceUID
        if (self.line1.line_id[0] != self.line2.line_id[0]) or (self.line1.line_id[-1] == self.line2.line_id[-1]):
            raise LineWithWrongIDsException()
        self.corner_points = ()

    def get_corner_points(self):

        if len(self.corner_points) == 0:
            x_values = [self.line1.x0, self.line1.x1, self.line2.x0, self.line2.x1]
            y_values = [self.line1.y0, self.line1.y1, self.line2.y0, self.line2.y1]

            left_upper_corner = (min(x_values), max(y_values))
            right_upper_corner = (max(x_values), max(y_values))
            left_down_corner = (min(x_values), min(y_values))
            right_down_corner = (max(x_values), min(y_values))

            self.corner_points = (left_upper_corner, right_upper_corner, right_down_corner, left_down_corner)

        return self.corner_points

    def __repr__(self):
        return "Line1: " + str(self.line1) + "; Line2: " + str(self.line2) + "; SOPInstanceUID: " + str(
            self.SOPInstanceUID)


class PatientMeningeomaMeasurements:
    # MEASUREMENT_REGEX = r"FL: \[([0,1].[0-9]*,\s[0,1].[0-9]*)\].*UI:\s([\.,0-9]*).*FL: \[([0,1].[0-9]*,\s[0,1].[0-9]*).*([0-9].[0-9])\]"
    MEASUREMENT_REGEX = r"FL: \[([0,1].[0-9]*,\s[0,1].[0-9]*)\].*UI:\s([\.,0-9]*).*FL: \[([0,1].[0-9]*,\s[0,1].[0-9]*).*Tracking UID:\s([a-z,0-9,-]*);\s([0-9].[0-9])\]"


    @staticmethod
    def create(path_to_file):

        if path_to_file == "":
            raise Exception("This patient has no measurements although it is a txt file")

        measurements = PatientMeningeomaMeasurements()

        with open(path_to_file, "r") as file:
            for line in file:
                value = line.strip()
                if value.startswith("["):
                    measurements.add_line(value)

        measurements.make_line_tuples()
        return measurements

    def __init__(self):
        self.lines = []
        self.measurements = []

    def add_line(self, input_string):
        match = re.search(PatientMeningeomaMeasurements.MEASUREMENT_REGEX, input_string)
        SOPInstanceUID = match.group(2)
        point0 = match.group(1)
        point1 = match.group(3)
        tracking_UID = match.group(4)
        line_id = match.group(5)
        self.lines.append(Line(point0, point1, line_id, SOPInstanceUID))

    def __repr__(self):
        return os.linesep.join([line.__repr__() for line in self.lines])

    def make_line_tuples(self):
        sorted_lines = sorted(self.lines, key=lambda x: float(x.line_id))
        for i in range(0, len(sorted_lines) - 1, 2):
            line1 = sorted_lines[i]
            line2 = sorted_lines[i + 1]
            line_tuple = MeningeomaMeasurement(line1, line2)
            self.measurements.append(line_tuple)
