import time
import unittest

from nose.tools import eq_

from helix.Services.dxf_helper import DXFHelper
from helix.Services.dxf_service import DXFService
from helix.constants.module_type_constants.dual_tilt_128_cell_constants import DualTilt128CellConstants
from helix.constants.module_type_constants.dual_tilt_96_cell_constants import DualTilt96CellConstants
from helix.constants.module_type_constants.dual_tilt_pseries_constants import DualTiltPSeriesConstants
from helix.constants.module_type_constants.single_tilt_128_cell_constants import SingleTilt128CellConstants
from helix.constants.module_type_constants.single_tilt_96_cell_constants import SingleTilt96CellConstants
from helix.constants.module_type_constants.single_tilt_pseries_constants import SingleTiltPSeriesConstants
from helix.constants.system_type import SystemType
from helix.models.dxf.polygon import Polygon
from helix.models.subarray import Subarray
from helix.validators.subarray_validator import SubarrayValidator
from test.fixtures.dxf.expected_dual_tilt_128_cell import expected_dual_tilt_128_cell_panels
from test.fixtures.dxf.expected_dual_tilt_96_cell import expected_dual_tilt_96_cell_panels
from test.fixtures.dxf.expected_dual_tilt_96_cell_fuzzy import expected_dual_tilt_96_cell_panels_fuzzy
from test.fixtures.dxf.expected_dual_tilt_pseries import expected_dual_tilt_pseries_panels
from test.fixtures.dxf.expected_single_tilt_128_cell import expected_single_tilt_128_cell_panels
from test.fixtures.dxf.expected_single_tilt_96_cell import expected_single_tilt_96_cell_panels
from test.fixtures.dxf.expected_single_tilt_96_cell import expected_single_tilt_96_cell_panels
from test.fixtures.dxf.expected_single_tilt_pseries import expected_single_tilt_pseries_panels


class DXFServiceTest(unittest.TestCase):
    def setUp(self):
        self.subject = DXFService()

    # def test_integration_parse_single_tilt_96_cell(self):
    #     with open('test/fixtures/dxf/input_single_tilt_96_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content,
    #                            SingleTilt96CellConstants(), SystemType.singleTilt,
    #                            58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     del result['buildings']
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #
    #     expected = {
    #         'panels': expected_single_tilt_96_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=550, start_row=0),
    #             Subarray(subarray_number=2, size=575, start_row=550),
    #             Subarray(subarray_number=3, size=638, start_row=1125),
    #             Subarray(subarray_number=4, size=667, start_row=1763),
    #         ]
    #     }
    #     for i in range(len(expected["panels"]) - 1):
    #         eq_(result["panels"][i], expected["panels"][i])
    #
    #     for i in range(len(expected["subarrays"]) - 1):
    #         eq_(result["subarrays"][i], expected["subarrays"][i])
    #
    # def test_integration_parse_dual_tilt_96_cell(self):
    #     with open('test/fixtures/dxf/input_dual_tilt_96_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTilt96CellConstants(), SystemType.dualTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_dual_tilt_96_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=87, start_row=0),
    #             Subarray(subarray_number=2, size=32, start_row=87),
    #             Subarray(subarray_number=3, size=40, start_row=119),
    #             Subarray(subarray_number=4, size=85, start_row=159),
    #             Subarray(subarray_number=5, size=28, start_row=244),
    #             Subarray(subarray_number=6, size=77, start_row=272),
    #             Subarray(subarray_number=7, size=95, start_row=349),
    #             Subarray(subarray_number=8, size=93, start_row=444),
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 8)
    #     eq_(len(result['panels']), 537)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_integration_parse_new_single_tilt_96_cell(self):
    #     with open('test/fixtures/dxf/input_new_single_tilt_96_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, SingleTilt96CellConstants(), SystemType.singleTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_new_single_tilt_96_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=216, start_row=0)
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 1)
    #     eq_(len(result['panels']), 216)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_integration_parse_new_dual_tilt_96_cell(self):
    #     with open('test/fixtures/dxf/input_new_dual_tilt_96_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTilt96CellConstants(), SystemType.dualTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_new_dual_tilt_96_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=135, start_row=0)
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 1)
    #     eq_(len(result['panels']), 135)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_integration_parse_dual_tilt_96_cell_fuzzy_wind_zone(self):
    #     with open('test/fixtures/dxf/input_dual_tilt_96_cell_angles_less_than_80.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTilt96CellConstants(),
    #                            SystemType.dualTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_dual_tilt_96_cell_panels_fuzzy,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=115, start_row=0),
    #             Subarray(subarray_number=2, size=327, start_row=115),
    #             Subarray(subarray_number=3, size=342, start_row=442),
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), len(expected['subarrays']))
    #     eq_(len(result['panels']), len(expected['panels']))
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_integration_parse_dual_tilt_128_pre_consolidated(self):
    #     with open('test/fixtures/dxf/input_dual_tilt_96_cell_preconsolidated.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTilt96CellConstants(),
    #                            SystemType.dualTilt,
    #                            58.7878,
    #                            DXFHelper(),
    #                            SubarrayValidator())
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['modules']), 1550)
    #
    # def test_integration_parse_new_single_tilt_128_cell(self):
    #     with open('test/fixtures/dxf/input_new_single_tilt_128_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, SingleTilt128CellConstants(), SystemType.singleTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_new_single_tilt_128_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=162, start_row=0)
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 1)
    #     eq_(len(result['panels']), 162)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_integration_parse_new_dual_tilt_128_cell(self):
    #     with open('test/fixtures/dxf/input_new_dual_tilt_128_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTilt128CellConstants(), SystemType.dualTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_new_dual_tilt_128_cell_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=100, start_row=0)
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 1)
    #     eq_(len(result['panels']), 100)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)

    def test_integration_parse_new_single_tilt_pseries(self):
        with open('test/fixtures/dxf/input_single_tilt_pseries.dxf', 'r',
                  newline='') as dxf_file:
            dxf_content = dxf_file.read()

        subject = DXFService()

        result = subject.parse(dxf_content, SingleTiltPSeriesConstants(), SystemType.singleTilt, 58.7878, DXFHelper(),
                               SubarrayValidator())

        expected = {
            'is_panel_drawing_inaccurate': False,
            'panels': expected_single_tilt_pseries_panels,
            'subarrays': [
                Subarray(subarray_number=1, size=63, start_row=0)
            ]
        }

        eq_(len(result['panels']), len(result['modules']))
        eq_(len(result['subarrays']), 1)
        eq_(len(result['panels']), 63)

        del result['modules']
        del result['size']
        del result['lb_polygons']
        del result['buildings']

        eq_(result, expected)

    # def test_integration_parse_new_dual_tilt_pseries(self):
    #     with open('test/fixtures/dxf/input_new_dual_tilt_pseries.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #
    #     subject = DXFService()
    #
    #     result = subject.parse(dxf_content, DualTiltPSeriesConstants(), SystemType.dualTilt, 58.7878, DXFHelper(),
    #                            SubarrayValidator())
    #
    #     expected = {
    #         'panels': expected_new_dual_tilt_pseries_panels,
    #         'subarrays': [
    #             Subarray(subarray_number=1, size=100, start_row=0)
    #         ]
    #     }
    #
    #     eq_(len(result['panels']), len(result['modules']))
    #     eq_(len(result['subarrays']), 1)
    #     eq_(len(result['panels']), 100)
    #
    #     del result['modules']
    #     del result['size']
    #     del result['lb_polygons']
    #     del result['buildings']
    #
    #     eq_(result, expected)
    #
    # def test_parse(self):
    #     mock_dxf_grabber = MagicMock()
    #
    #     dxf_return_values = [
    #         MagicMock(),
    #         MagicMock()
    #     ]
    #
    #     mock_dxf_grabber.return_value = MagicMock(entities=dxf_return_values)
    #     dxf_helper = MagicMock()
    #
    #     subarray_validator = MagicMock()
    #
    #     buildings = [Polygon(points=[(0, 0), (0, 10), (10, 10), (10, 0)])]
    #     modules = [Polygon(points=[(0, 0), (0, 5), (5, 5), (5, 0)])]
    #     dxf_helper.build_polygons.return_value = (buildings, modules)
    #     dxf_helper.consolidate_dual_tilt_modules.return_value = modules
    #
    #     translated_buildings = [Polygon(points=[(0, 0), (0, 4), (4, 4), (4, 0)])]
    #     translated_modules = [Polygon(points=[(0, 0), (0, 1), (1, 1), (1, 0)])]
    #     dxf_helper.translate_towards_origin.return_value = (translated_buildings, translated_modules)
    #
    #     panels = [MagicMock(), MagicMock()]
    #     panel_graph = [MagicMock()]
    #     subarrays = [Subarray(subarray_number=0)]
    #
    #     dxf_helper.generate_panels.return_value = panels
    #     dxf_helper.build_node_graph.return_value = panel_graph
    #     dxf_helper.detect_subarrays.return_value = subarrays
    #     dxf_helper.should_consolidate_modules.return_value = True
    #     dxf_helper.is_new_aurora_format.return_value = False
    #
    #     module_constants = MagicMock(panel_spacing=(2, 2))
    #     system_type = MagicMock()
    #     l_b = MagicMock()
    #     module_format = None
    #     subject = DXFService()
    #
    #     with patch('dxfgrabber.read', mock_dxf_grabber):
    #         result = subject.parse("doesn't matter",
    #                                module_constants,
    #                                system_type,
    #                                l_b, dxf_helper,
    #                                subarray_validator)
    #
    #     assert mock_dxf_grabber.called
    #     dxf_helper.build_polygons.assert_called_once_with(dxf_return_values)
    #     dxf_helper.consolidate_dual_tilt_modules.assert_called_once_with(modules, system_type, module_format)
    #
    #     dxf_helper.translate_towards_origin.assert_called_once_with(buildings, modules)
    #
    #     dxf_helper.generate_panels.assert_called_once_with(modules, translated_modules)
    #
    #     dxf_helper.build_node_graph.assert_called_once_with(panels, module_constants.panel_spacing)
    #
    #     dxf_helper.detect_subarrays.assert_called_once_with(panel_graph, panels)
    #     dxf_helper.detect_panel_types.assert_called_once_with(panel_graph)
    #     dxf_helper.detect_wind_zones.assert_called_once_with(panels,
    #                                                          translated_buildings,
    #                                                          translated_modules,
    #                                                          l_b, system_type)
    #     subarray_validator.validate_subarray.assert_called_once_with(panel_graph,
    #                                                                  0,
    #                                                                  system_type)
    #
    #     eq_(result, {
    #         'size': (4, 4),
    #         'buildings': translated_buildings,
    #         'modules': translated_modules,
    #         'panels': panels,
    #         'subarrays': subarrays,
    #         'lb_polygons': dxf_helper.l_b_polygons()
    #     })
    #
    # # Performance tests.
    #
    # def test_dxf_service_performance_dual_tilt_96_cell(self):
    #     with open('test/fixtures/dxf/input_dual_tilt_96_cell.dxf', 'r',
    #               newline='') as dxf_file:
    #         dxf_content = dxf_file.read()
    #     subject = DXFService()
    #
    #     results = []
    #
    #     run_count = 1
    #
    #     last_result = None
    #
    #     for _ in range(run_count):
    #         start = time.clock()
    #         last_result = subject.parse(dxf_content, DualTilt96CellConstants(), SystemType.dualTilt, 40, DXFHelper(),
    #                                     SubarrayValidator())
    #         end = time.clock()
    #         results.append(end - start)
    #
    #     average_run_time = sum(results) / run_count
    #
    #     eq_(len(last_result['subarrays']), 8)
    #     assert average_run_time < 10, "Expected to take less than 10 seconds on average to parse even large dxfs"
    #
    #     print("%d runs took on average %f seconds" % (run_count, sum(results) / run_count))
