from utils_workspace_manger import *
from utils_evolution_tools import *
from utils_coordinates import *
from utils_server_client import *

class RoofShowcase:
    m_sum = ShapeUtils.FuncMode.SUM
    m_min = ShapeUtils.FuncMode.MIN
    m_max = ShapeUtils.FuncMode.MAX
    default_point = Coordinates(112,0,0)
    
    def __init__(self, a, b, mask=None) -> None:
        self.a = a
        self.b = b
        self.mask = mask
    
    def _get_roof_coordinates(self, mode, x2, z2, cx2, cz2, mode2, x1, z1, cx1, cz1, mode1, fx1, fz1, cfx1, cfz1, fmode1):
        return ShapeUtils.np_array_to_coordinates(
            ShapeUtils.roof(self.a,self.b, mode,
                x2, z2, cx2, cz2, mode2,
                x1, z1, cx1, cz1, mode1,
                fx1, fz1, cfx1, cfz1, fmode1
            ),
            mask=self.mask
        )
    
    def quadratic_roofs(self, mode, c):
        return [
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,c,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_max, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_max, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,c,0,0,self.m_max, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_min, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_min, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,c,0,0,self.m_min, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
        ]
    
    def linear_roofs(self, mode, c):
        return [       
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,c,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_max, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,0,0,0,self.m_max, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,c,0,0,self.m_max, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_min, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,0,0,0,self.m_min, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, c,c,0,0,self.m_min, 0,0,0,0,self.m_sum),
        ]
    
    def fractional_roofs(self, mode, c):
        return [
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_max),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,0,0,0,self.m_max),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,c,0,0,self.m_max),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_min),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,0,0,0,self.m_min),
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, c,c,0,0,self.m_min),
        ]
    
    def combination_roofs(self, mode, c):
        return [
            self._get_roof_coordinates(mode, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_sum, 0,c,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_sum, 0,c,0,0,self.m_sum, 0,0,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_sum, 0,0,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_sum, 0,c,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_sum, c,0,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, 0,c,0,0,self.m_sum, c,0,0,0,self.m_sum, 0,c,0,0,self.m_sum),
            self._get_roof_coordinates(mode, c,0,0,0,self.m_sum, 0,c,0,0,self.m_sum, 0,c,0,0,self.m_sum),
        ]
    
    def all_shapes_roofs(self, mode, c):
        return (
            self.quadratic_roofs(mode,c) +
            self.linear_roofs(mode,c) +
            self.fractional_roofs(mode,c) +
            self.combination_roofs(mode,c)
        )
    
    def roofs_showcase(self, sc:ServerClient, coor:Coordinates, c):
        ws = WorkspaceManager(sc)
        ws.create_grid_workspace(
            coor,
            Coordinates(9, 1, 3*4),
            Coordinates(self.a, 200, self.b),
            Coordinates(3, 3, 3)
        )

        roofs = (
            self.all_shapes_roofs(RoofShowcase.m_sum,c) +
            self.all_shapes_roofs(RoofShowcase.m_max,c) +
            self.all_shapes_roofs(RoofShowcase.m_min,c)
        )

        block_list = []
        for coor,roof in zip(ws.get_coordinates_list(),roofs):
            block_list +=[ServerClient.create_block(coor+block, STONE) for block in roof]
        sc.place_blocks_from_list(block_list)

        sc.ask_for_response("Send \"/response\" if u want to end showcase")
        ws.delete_workspace_grid()
    
    @staticmethod
    def default_roofs_showcase(sc:ServerClient, c=1, a=5, b=5, shape=None):
        mask = ShapeUtils.fill_shape(shape(a, b)) if shape !=None else None
        rs = RoofShowcase(a, b, mask)
        rs.roofs_showcase(sc, RoofShowcase.default_point, c)

if __name__ == '__main__':
    sc = ServerClient()
    shape_fs = [
        None,
        ShapeUtils.ellipse,
        lambda a,b: ShapeUtils.rhomboid(a,b,2,0),
        lambda a,b: ShapeUtils.rhomboid(a,b,-2,0),
        lambda a,b: ShapeUtils.rhomboid(a,b,0,2),
        lambda a,b: ShapeUtils.rhomboid(a,b,0,-2)
    ]
    for shape_f in shape_fs:
        RoofShowcase.default_roofs_showcase(sc, shape=shape_f)
        RoofShowcase.default_roofs_showcase(sc, c=-1, shape=shape_f)
        RoofShowcase.default_roofs_showcase(sc, c=2, shape=shape_f)
        RoofShowcase.default_roofs_showcase(sc, a=10, b=10, shape=shape_f)
