from numpy import array, ceil

from helix.calculators.bom_helper import add_parts_to_list, apply_package_size_rounding
from helix.calculators.ebom_calculator import EbomCalculator
from helix.calculators.mechanical_bom_calculator import MechanicalBomCalculator
from helix.constants.parts import *


class BomCalculator(object):
    def __init__(self, values, panels, subarrays, graph_repository):
        self.values = values
        self.panels = panels
        self.subarrays = subarrays
        self.graph_repository = graph_repository

    def compute_bom(self):
        output_array = []
        for part, quantity in self.parts_list().items():
            if ceil(quantity) <= 0:
                continue
            row = list(part)
            row.append(int(ceil(quantity)))
            output_array.append(row)

        output_array.sort(key=lambda x: x[0] + x[1])
        return array(output_array)

    def documentation_bom(self):
        parts_list = self.parts_list()

        for part in all_parts:
            if part not in parts_list.keys():
                parts_list[part] = 0

        output_array = []
        for part, quantity in parts_list.items():
            if part == ballast:
                row = 'ballast'
            elif part == anchor:
                row = 'anchors'
            elif part == module:
                row = 'modules'
            else:
                row = part[0]
            quantity = max(0, quantity)
            output_array.append((row, int(ceil(quantity))))
        return output_array

    def parts_list(self):
        row_count = sum(subarray.row_count for subarray in self.subarrays)
        column_count = sum(subarray.column_count for subarray in self.subarrays)
        parts_list = MechanicalBomCalculator(self.values, self.panels, self.subarrays).mechanical_bom()
        ebom_parts_list = EbomCalculator(self.values, ceil(row_count), ceil(column_count), parts_list.get(module), self.subarrays).compute_ebom()

        add_parts_to_list(parts_list, ebom_parts_list)

        apply_package_size_rounding(parts_list, package_sizes)
        return parts_list
