from numpy import array
from numpy.ma import log

from helix.constants.global_constants import minimum_racking_capacity
from helix.constants.panel_type import PanelType
from helix.constants.system_type_constants.single_tilt_constants import SingleTiltConstants


class SingleTiltPSeriesConstants(object):
    tolerance = 0.1 #require 10% additional space for panel spacing
    panel_spacing = (82.0, 61.8755)  # inches
    presenter_spacing = (1.5, 1)
    panel_area = 22.22
    surface_area = 22.22
    tributary_area = array([1.87, 3.24, 3.24, 3.82])
    ground_coverage_ratio = 0.67
    friction_coefficient = 0.42
    seismic_anchor_interval_constants = (8.9964, 2.09916)
    max_psf = 32
    system_constants = SingleTiltConstants()

    def c_p_lower_bound(self):
        c_p_lower_bound = []
        for index, area in enumerate(self.tributary_area):
            if area < 9:
                c_p = -0.0273 * log(area) + 0.1401
            else:
                c_p = -0.0146 * log(area) + 0.112
            edge_factor = self.edge_factor(self.system_constants.wind_zones[-1], PanelType.from_index(index))
            c_p_lower_bound.append(c_p * edge_factor)
        return array(c_p_lower_bound)

    def edge_factor(self, wind_zone, panel_type):
        # corner, north/south, east/west, middle
        edge_matrix = {'A': [1.2, 1.2, 1.0, 1.0],
                       'B': [1.2, 1.2, 1.0, 1.0],
                       'C': [1.4, 1.4, 1.0, 1.0],
                       'D': [1.4, 1.4, 1.0, 1.0],
                       'E': [1.5, 1.0, 1.5, 1.0],
                       'F': [1.3, 1.3, 1.0, 1.0],
                       'G': [1.0, 1.0, 1.0, 1.0],
                       'H': [1.0, 1.0, 1.0, 1.0],
                       'I': [1.0, 1.0, 1.0, 1.0],
                       'J': [2.0, 2.0, 1.0, 1.0],
                       'K': [1.4, 1.4, 1.0, 1.0]}
        return edge_matrix[wind_zone][panel_type.index()]

    def racking_capacity(self, panel_type):
        if panel_type == PanelType.Corner or panel_type == PanelType.EastWest:
            return minimum_racking_capacity
        else:
            return 308

    def c_p_constants(self, A_n, wind_zone):
        if wind_zone == 'A':
            if A_n < 421.5:
                return -0.2245, 1.717
            elif A_n < 2294.7:
                return -0.1298, 1.1446
            else:
                return -0.0308, 0.3787
        elif wind_zone == 'B':
            if A_n < 421.5:
                return -0.1818, 1.3585
            elif A_n < 2294.7:
                return -0.0708, 0.688
            else:
                return -0.0308, 0.3787
        elif wind_zone == 'C':
            if A_n < 421.5:
                return -0.0735, 0.6443
            elif A_n < 2294.7:
                return -0.059, 0.5566
            else:
                return -0.021, 0.2627
        elif wind_zone == 'D':
            if A_n < 187.3:
                return -0.1007, 0.6868
            elif A_n < 421.5:
                return -0.049, 0.4181
            else:
                return -0.0183, 0.2304
        elif wind_zone == 'E':
            if A_n < 187.3:
                return -0.058, 0.4236
            elif A_n < 421.5:
                return -0.0518, 0.391
            else:
                return -0.0125, 0.1533
        elif wind_zone == 'F':
            if A_n < 187.3:
                return -0.0655, 0.4682
            elif A_n < 421.5:
                return -0.0518, 0.391
            else:
                return -0.0125, 0.1533
        elif wind_zone == 'G':
            if A_n < 187.3:
                return -0.0341, 0.2786
            elif A_n < 421.5:
                return -0.0271, 0.242
            else:
                return -0.0125, 0.1533
        elif wind_zone == 'H':
            if A_n < 187.3:
                return -0.1161, 0.7872
            elif A_n < 421.5:
                return -0.074, 0.5672
            elif A_n < 1685.9:
                return -0.0433, 0.3816
            else:
                return -0.0117, 0.1473
        elif wind_zone == 'I':
            if A_n < 187.3:
                return -0.3856, 2.258
            elif A_n < 421.5:
                return -0.148, 1.0143
            elif A_n < 1685.9:
                return -0.0433, 0.3816
            else:
                return -0.0117, 0.1473
        elif wind_zone == 'J':
            if A_n < 187.3:
                return -0.1024, 0.6557
            elif A_n < 421.5:
                return -0.0518, 0.391
            else:
                return -0.0125, 0.1533
        else:
            return 1, 1

    def base_weight(self, panel_type, tray_count):
        return [[65.02, 65.02, 68.17, 71.32],
                [62.05, 62.05, 65.20, 68.35],
                [62.87, 64.73, 67.88, 71.03],
                [60.26, 62.11, 65.26, 68.41]][panel_type.index()][tray_count]

    def link_tray_thresholds(self, panel_type):
        return [[0, 13.0],
                [0, 10.00],
                [7, 14.5],
                [6, 11.0]][panel_type.index()]

    def cross_tray_thresholds(self, panel_type):
        return [[13.0, 21.0, 29.0],
                [10.00, 18.0, 26.0],
                [14.5, 22.5, 30.5],
                [11.0, 19.0, 27.0]][panel_type.index()]

    def weighted_average_c_p(self, corner, north_south, east_west, middle):
        """ Based on a 30 by 28 rectangular array """
        return (middle * 182. + north_south * 14. + east_west * 13. + corner) / 210.

    def minimum_a_n_coefficients(self, uplift_c_p, wind_zone):
        if wind_zone == 'A':
            if uplift_c_p > 0.360:
                return 3.1178, 0.3769
            elif uplift_c_p > 0.180:
                return 2.4967, 0.274
            else:
                return 0.9691, 0.0685
        elif wind_zone == 'B':
            if uplift_c_p > 0.260:
                return 2.3762, 0.2807
            elif uplift_c_p > 0.160:
                return 1.7699, 0.1803
            else:
                return 0.7209, 0.0392
        elif wind_zone == 'C':
            if uplift_c_p > 0.200:
                return 1.7251, 0.215
            elif uplift_c_p > 0.100:
                return 1.2668, 0.1274
            else:
                return 0.4655, 0.0196
        elif wind_zone == 'D':
            if uplift_c_p > 0.120:
                return 2.3762, 0.2807
            elif uplift_c_p > 0.094:
                return 1.7699, 0.1803
            else:
                return 0.7209, 0.0392
        elif wind_zone == 'E':
            if uplift_c_p > 0.078:
                return 0.8096, 0.0976
            elif uplift_c_p > 0.060:
                return 0.438, 0.0361
            else:
                return 0.3227, 0.0206
        elif wind_zone == 'F':
            if uplift_c_p > 0.078:
                return 0.6281, 0.0708
            else:
                return 0.328, 0.0212
        elif wind_zone == 'G':
            if uplift_c_p > 0.078:
                return 0.6281, 0.0708
            else:
                return 0.328, 0.0212
        elif wind_zone == 'H':
            if uplift_c_p > 0.180:
                return 1.8215, 0.2525
            elif uplift_c_p > 0.120:
                return 1.4679, 0.185
            elif uplift_c_p > 0.060:
                return 1.13479, 0.1298
            else:
                return 0.3227, 0.0206
        elif wind_zone == 'I':
            if uplift_c_p > 0.240:
                return 4.3609, 0.6996
            elif uplift_c_p > 0.120:
                return 2.639, 0.3699
            elif uplift_c_p > 0.060:
                return 1.4027, 0.1659
            else:
                return 0.3277, 0.0206
        elif wind_zone == 'J':
            if uplift_c_p > 0.120:
                return 0.7131, 0.0891
            elif uplift_c_p > 0.078:
                return 0.5503, 0.058
            else:
                return 0.328, 0.0212
        elif wind_zone == 'K':
            if uplift_c_p > 0.080:
                return 0.3, 0.0455
            else:
                return 0.2465, 0.0212
        else:
            return 1, 1

