import copy
from helix.calculators.subarray_graph import SubarrayGraph, Direction
from helix.calculators.subarray_helper import extract_subarray
from helix.constants.panel_type import PanelType


class GraphRepository(object):
    def __init__(self, panels, subarrays, system_type):
        self.graphs = {}
        for subarray in subarrays:
            subarray_panels = extract_subarray(panels, subarray.subarray_number)
            self.graphs[subarray.subarray_number] = SubarrayGraph(panels=subarray_panels, system_type=system_type)

        def walk_callback(_, next_direction, direction_to_get_here):
            if next_direction == Direction.North:
                self.rows_perimeter += 1
            elif next_direction == Direction.East:
                self.columns_perimeter += 1

        for subarray in subarrays:
            graph = self.graphs[subarray.subarray_number]

            subarray_panels = extract_subarray(panels, subarray.subarray_number)
            rows_fallback = sum(1 for panel in subarray_panels if panel.panel_type == PanelType.Corner or panel.panel_type == PanelType.EastWest) / 2
            columns_fallback = sum(1 for panel in subarray_panels if panel.panel_type == PanelType.Corner or panel.panel_type == PanelType.NorthSouth) / 2

            if len(graph.nodes) == 0:
                subarray.row_count = rows_fallback
                subarray.column_count = columns_fallback
                subarray.row_counted_geometrically = False
                subarray.column_counted_geometrically = False
                continue
            self.rows_perimeter = 1
            self.columns_perimeter = 1
            graph.walk_graph_perimeter(graph.lower_left_node(graph.nodes), walk_callback, repeat_steps=False)
            subarray.row_count = max(self.rows_perimeter, rows_fallback)
            subarray.row_counted_geometrically = self.rows_perimeter >= rows_fallback
            subarray.column_count = max(self.columns_perimeter, columns_fallback)
            subarray.column_counted_geometrically = self.columns_perimeter >= columns_fallback

    def subarray_graph(self, subarray_number):
        return copy.deepcopy(self.graphs[subarray_number])
