import io

import dxfgrabber


class DXFService(object):
    """
    Takes the contents of a DXF file and creates modules, buildings, panels,
    subarrays, and polygons based on the data
    """

    # l_b is expected to be in inches, not feet!
    def parse(self, dxf_file_contents, module_constants, system_type, l_b, dxf_helper, subarray_validator):
        """Parse will generate the panels, subarrays, buildings
        and modules that are present in the dxf file

        Arguments:
            dxf_file_contents (str) Content of the uploaded file
        """

        dxf = dxfgrabber.read(io.StringIO(dxf_file_contents, newline=None))

        buildings, modules = dxf_helper.build_polygons(dxf.entities)

        """
        A new type of aurora format file was added in the project
        The visibile difference if you read the file, is that the
        new format contains the string buildings.
        The old version doesn't

        """

        pair_spacing = None
        dxf_helper.is_new_aurora_format()
        if hasattr(module_constants, "spacing_size_inches"):
            pair_spacing = module_constants.spacing_size_inches

        if dxf_helper.should_consolidate_modules(modules, system_type,
                                                 module_constants):
            modules = dxf_helper.consolidate_dual_tilt_modules(modules,
                                                               system_type,
                                                               pair_spacing)

        translated_buildings, translated_modules = dxf_helper.translate_towards_origin(buildings, modules)
        translated_buildings_ccw = dxf_helper.get_polygons_counterclockwise(translated_buildings)
        buildings_ccw = dxf_helper.get_polygons_counterclockwise(buildings)



        panels = dxf_helper.generate_panels(modules, translated_modules)
        # FIXME: Building a graph with many entities is very slow
        node_graph = dxf_helper.build_node_graph(panels, module_constants.panel_spacing)
        subarrays = dxf_helper.detect_subarrays(node_graph, panels)
        for subarray in subarrays:
            subarray_validator.validate_subarray(node_graph, subarray.subarray_number, system_type)
        dxf_helper.detect_panel_types(node_graph)
        dxf_helper.detect_wind_zones(panels, translated_buildings_ccw, translated_modules, l_b, system_type)

        all_points = [p.points for p in translated_buildings_ccw + translated_modules]

        points = [point for points_list in all_points for point in points_list]

        max_x = max(p[0] for p in points)
        max_y = max(p[1] for p in points)

        panel_orientation = panels[0].coordinate.rotation

        return {
            'size': (max_x, max_y),  # Used for debugging
            'buildings': buildings_ccw,
            'modules': translated_modules,
            'panels': panels,
            'subarrays': subarrays,
            'lb_polygons': dxf_helper.l_b_polygons(translated_buildings_ccw, l_b, system_type, panel_orientation),
            'is_panel_drawing_inaccurate': self.is_panel_drawing_inaccurate(panels)
        }

    def is_panel_drawing_inaccurate(self,panels):
        '''True if subarrays are not rotated more than allowed tolerance, false otherwise'''
        ROTATION_ACCURACY_DELTA_DEGREES = 0.1

        if panels is None or panels == []:
            return True

        first_panel_rotation = panels[0].coordinate.rotation # rotation is in degrees

        for panel in panels:
            difference = abs(first_panel_rotation - panel.coordinate.rotation)
            if difference >= ROTATION_ACCURACY_DELTA_DEGREES:
                return True

        return False
