import unittest
from unittest.mock import MagicMock

from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.anchor_type import AnchorType
from helix.constants.module_type import ModuleType
from helix.constants.panel_type import PanelType
from helix.constants.parts import *
from helix.constants.system_type import SystemType
from helix.models.panel import Panel
from helix.models.subarray import Subarray
from test.test_helpers import assert_dictionary_equal


class MechanicalBomCalculatorWhenSingleTiltPSeriesTest(unittest.TestCase):
    def setUp(self):
        self.values = MagicMock()
        self.values.system_type.return_value = SystemType.singleTilt
        self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip_Plus
        self.values.module_type.return_value = ModuleType.PSeries

        """
            Generated using the following parameters:
            Building Height = 30
            Building Length = 200
            Building Width = 76
            Parapet Height = 0
            Wind Speed = 125
            Exposure Category = C
            Anchor type = OMG PowerGrip Plus
            Ballast Block Weight = 13
            Max Allowable System Pressure = 10
            System type = Single Tilt
        """

        panels = [
            Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=6, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
            Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
            Panel(wind_zone=0, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=1, subarray=0),
            Panel(wind_zone=1, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=1, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=2, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=2, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=3, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=3, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=3, panel_type=PanelType.Middle, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=4, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=4, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=5, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=5, panel_type=PanelType.EastWest, ballast=4, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=2, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=7, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=7, panel_type=PanelType.Middle, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=8, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=8, panel_type=PanelType.EastWest, ballast=0, link_tray=2, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=6, link_tray=1, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=9, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0, wind_anchors=1, seismic_anchors=0, subarray=0),
            Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=9, panel_type=PanelType.Middle, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=10, panel_type=PanelType.Corner, ballast=4, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=10, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=10, panel_type=PanelType.EastWest, ballast=1, link_tray=2, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0),
            Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, seismic_anchors=0, subarray=0)
        ]

        subarrays = [
            Subarray(subarray_number=0, required_seismic_anchors=2, row_count=2, column_count=24, row_counted_geometrically=True, column_counted_geometrically=True)
        ]

        self.subject = MechanicalBomCalculator(self.values, panels, subarrays)

    def test_compute_mechanical_bom(self):
        expected_output = {
            wire_clip: 88,
            single_tilt_chassis: 46.31,
            following_tray: 25,
            link_tray: 28,
            spoiler_1_1: 44,
            left_deflector_1_1: 11,
            right_deflector_1_1: 11,
            anchor_plate: 15,
            cross_tray_1_1: 5,
            rubber_foot: 4.4,
            front_skirt_1_1: 24,
            rear_skirt_1_1: 44,
            leading_tray: 25,
            ballast: 192,
            anchor: 15,  # 12 + the 3 seismic anchors
            anchor_washer: 15,
            module: 44
        }

        assert_dictionary_equal(self.subject.mechanical_bom(), expected_output)
