import os
from .config import Config
from .robot import Robot
from .processor import Processor
from .message import bright, info, error


class ProcessorSimplifySTLs(Processor):
    """
    Allow for mesh simplifications using MeshLab
    """

    def __init__(self, config: Config):
        super().__init__(config)

        # STL merge / simplification
        self.simplify_stls = config.get("simplify_stls", False)
        self.max_stl_size = config.get("max_stl_size", 3)

        if self.simplify_stls:
            self.pymeshlab = self.check_meshlab()

    def check_meshlab(self):
        print(bright("* Checking pymeshlab presence..."))
        try:
            import pymeshlab

            return pymeshlab
        except ImportError:
            self.simplify_stls = False
            print(error("No pymeshlab, disabling STL simplification support"))
            print(info("TIP: consider installing pymeshlab:"))
            print(info("pip install pymeshlab"))

    def process(self, robot: Robot):
        if self.simplify_stls:
            simplify_all = (
                self.simplify_stls != "visual" and self.simplify_stls != "collision"
            )
            simplified = set()
            getcwd = os.getcwd()
            # Changing directory to output to have relative paths working
            os.chdir(self.config.output_directory)
            for link in robot.links:
                for part in link.parts:
                    for mesh in part.meshes:
                        if (
                            simplify_all or mesh.is_type(self.simplify_stls)
                        ) and mesh.filename not in simplified:
                            simplified.add(mesh.filename)
                            self.simplify_stl(mesh.filename)
            os.chdir(getcwd)

    def reduce_faces(self, filename: str, reduction: float = 0.9):
        mesh_set = self.pymeshlab.MeshSet()

        # Add input mesh
        mesh_set.load_new_mesh(filename)

        # Apply filter
        mesh_set.apply_filter(
            "meshing_decimation_quadric_edge_collapse",
            targetperc=reduction,
            qualitythr=0.5,
            preserveboundary=False,
            boundaryweight=1,
            preservenormal=True,
            preservetopology=False,
            optimalplacement=True,
            planarquadric=True,
            qualityweight=False,
            planarweight=0.001,
            autoclean=True,
            selected=False,
        )

        # Save mesh
        mesh_set.save_current_mesh(filename)

    def simplify_stl(self, filename: str):
        size_M = os.path.getsize(filename) / (1024 * 1024)

        if size_M > self.max_stl_size:
            print(
                info(
                    f"+ {os.path.basename(filename)} is {size_M:.2f} M, running mesh simplification"
                )
            )
            self.reduce_faces(filename, self.max_stl_size / size_M)
