import sys
from math import sqrt, atan, degrees
from helix.models.corner import Corner

class ProjectPresenter(object):
    def __init__(self, system_type, module_type):
        self.offset = None
        self.system_type = system_type
        self.module_type = module_type

    '''"This function expects coordinates to be in unit values, processed in coordinates_calculator.py" '''
    def get_panel_data(self, panels, subarrays, max_y = None):
        if self.offset is not None:
            raise RuntimeError("ProjectPresenter panels must be computed before buildings")

        table_data = []

        system_constants = self.system_type.system_constants()
        module_constants = self.system_type.module_constants(self.module_type)
        spacing_x, spacing_y = module_constants.presenter_spacing
        wind_zones = system_constants.wind_zones

        for panel in panels:
            subarray = [x for x in subarrays if x.subarray_number == panel.subarray][0]
            origin = subarray.origin

            table_data.append({
                'x': (panel.coordinate.x + origin.x) * spacing_x,
                'y': (panel.coordinate.y + origin.y) * spacing_y,
                'width': spacing_x,
                'height': spacing_y,
                'data': {
                    'panel_id': panel.id,
                    'panel_type': panel.panel_type.number(),
                    'ballast': panel.ballast,
                    'wind_anchors': panel.wind_anchors,
                    'seismic_anchors': panel.seismic_anchors,
                    'wind_zones': wind_zones[panel.wind_zone],
                    'link_trays': panel.presented_link_tray,
                    'cross_trays': panel.cross_tray,
                    'psf': round(panel.pressure, 2),
                    'subarray': panel.subarray
                }
            })

        # Move coordinates to reflect origin being at top-left
        # (as per canvas) instead of bottom-left
        height = max(map(lambda row: row['y'], table_data))
        first_cell = min(map(lambda row: row['y'], table_data))
        self.offset = height
        for panel in table_data:
            panel['y'] = height - panel['y'] + first_cell

        return table_data

    def get_buildings(self, buildings, max_y):
        if self.offset is None:
            self.offset = 0

        module_constants = self.system_type.module_constants(self.module_type)
        spacing_x, spacing_y = module_constants.presenter_spacing
        # max_y = -sys.maxsize - 1 # for flipping the y coordinate

        result = []
        for building in buildings:
            presentable_building = []
            result.append(presentable_building)
            # origin = self.find_origin(building)
            for point in building:
                point.x = point.x * spacing_x
                point.y = abs((point.y * spacing_y - max_y))
                presentable_building.append(point.__dict__)

        return result

    def get_corners(self, buildings):
        result = []
        for building in buildings:
            presentable_building = []
            result.append(presentable_building)
            previous_corner = building[-1]
            for i, corner in enumerate(building):
                if (i+1 == len(building)):
                    next_corner = building[0]
                else:
                    next_corner = building[i+1]
                
                corner_length_ccw = sqrt((next_corner[0] - corner[0])**2 + (next_corner[1] - corner[1])**2)
                corner_length_cw = sqrt((previous_corner[0] - corner[0])**2 + (previous_corner[1] - corner[1])**2)
                k1 = (corner[1] - previous_corner[1]) / (corner[0] - previous_corner[0])
                k2 = (next_corner[1] - corner[1]) / (next_corner[0] - corner[0])
                theta2 = degrees(atan(k2))
                theta1 = degrees(atan(k1)) - theta2
                if (theta1 < 0):
                    if (k1 < 0 and k2 < 0):
                        theta1 = 360 + theta1
                    elif (k1 < 0 and k2 > 0):
                        theta1 = 180 + theta1
                else:
                    if (k1 > 0 and k2 > 0):
                        theta1 = 180 + theta1
                
                if (theta1 < 135):
                    presentable_building.append(Corner(corner[0], corner[1], corner_length_ccw,corner_length_cw, theta1).__dict__)
                previous_corner = corner

        return result

    def get_max_y(self,buildings, panels):

        module_constants = self.system_type.module_constants(self.module_type)
        _, spacing_y = module_constants.presenter_spacing
        all_y = []

        if buildings is None or buildings == []: # no buildings in the file, probably CSV coordinates loaded
            for panel in panels:
                all_y.append(panel.coordinate.y)

        for building in buildings:
            for point in building:
                all_y.append(point.y)
        return max(all_y) * spacing_y

