from panda3d.core import PNMImage, SamplerState, Texture, Vec4

from rpcore.render_stage import RenderStage


class SelectionOutlineStage(RenderStage):

    required_pipes = ["ShadedScene"]

    def __init__(self, pipeline):
        RenderStage.__init__(self, pipeline)
        self._enabled = False
        self._outline_color = Vec4(1.0, 0.55, 0.0, 1.0)
        self._outline_width = 2.0
        self._fill_alpha = 0.0
        self._mask_tex = self._make_default_mask()

    @property
    def produced_pipes(self):
        return {"ShadedScene": self.target.color_tex}

    def create(self):
        self.target = self.create_target("SelectionOutline")
        self.target.add_color_attachment(bits=16)
        self.target.prepare_buffer()
        self._apply_inputs()

    def reload_shaders(self):
        self.target.shader = self.load_plugin_shader("selection_outline.frag.glsl")
        self._apply_inputs()

    def set_mask_texture(self, mask_texture):
        self._mask_tex = mask_texture if mask_texture else self._make_default_mask()
        self._apply_inputs()

    def set_enabled_outline(self, enabled):
        self._enabled = bool(enabled)
        self._apply_inputs()

    def set_outline_style(self, color=None, width_px=None, fill_alpha=None):
        if color is not None:
            self._outline_color = Vec4(color)
        if width_px is not None:
            self._outline_width = max(0.0, float(width_px))
        if fill_alpha is not None:
            self._fill_alpha = max(0.0, min(1.0, float(fill_alpha)))
        self._apply_inputs()

    def _apply_inputs(self):
        enabled_val = 1.0 if self._enabled else 0.0
        self.target.set_shader_input("SelectionMaskTex", self._mask_tex)
        self.target.set_shader_input("SelectionOutlineEnabled", enabled_val)
        self.target.set_shader_input("SelectionOutlineColor", self._outline_color)
        self.target.set_shader_input("SelectionOutlineWidth", self._outline_width)
        self.target.set_shader_input("SelectionFillAlpha", self._fill_alpha)

    def _make_default_mask(self):
        image = PNMImage(1, 1, 4)
        image.fill(0.0, 0.0, 0.0)
        image.alpha_fill(0.0)
        texture = Texture("selection_outline_default_mask")
        texture.load(image)
        texture.set_minfilter(SamplerState.FT_nearest)
        texture.set_magfilter(SamplerState.FT_nearest)
        texture.set_wrap_u(SamplerState.WM_clamp)
        texture.set_wrap_v(SamplerState.WM_clamp)
        return texture

