import bisect

from PIL import Image, ImageFilter

from learn_sql_model.optional import _optional_import_

pygame = _optional_import_("pygame", group="game")


def rot_center(image, angle):
    """rotate an image while keeping its center and size"""
    orig_rect = image.get_rect()
    rot_image = pygame.transform.rotate(image, angle)
    rot_rect = orig_rect.copy()
    rot_rect.center = rot_image.get_rect().center
    rot_image = rot_image.subsurface(rot_rect).copy()
    return rot_image


class Light:
    def __init__(self, game):
        self.game = game
        self.surf = pygame.Surface(
            (self.game.screen.get_width(), self.game.screen.get_height()),
            pygame.SRCALPHA,
            32,
        )
        self.surf.set_colorkey((0, 0, 0))
        self.pre_render()

    def pre_render(self):

        # self.lights = {}
        # for deg in range(-360, 360, 20):
        #     print("loading light", deg)
        #     self.lights[deg] = pygame.image.load(
        #         f"lights/light-{deg}.png"
        #     ).convert_alpha()
        # return

        light_surf = pygame.Surface(
            (
                self.game.player.hero.flashlight_strength * 3,
                self.game.player.hero.flashlight_strength * 3,
            ),
            pygame.SRCALPHA,
            32,
        )

        v = pygame.math.Vector2(0, 1)
        v.scale_to_length(self.game.player.hero.flashlight_strength)
        for r in range(-90 - 25, -90 + 25):
            _v = v.rotate(r)
            pygame.draw.line(
                light_surf,
                (255, 250, 205),
                (light_surf.get_width() / 2, light_surf.get_height() / 2),
                (
                    light_surf.get_width() / 2 + _v.x,
                    light_surf.get_height() / 2 + _v.y,
                ),
                50,
            )
        pygame.draw.circle(
            light_surf,
            (255, 250, 205),
            (light_surf.get_width() / 2, light_surf.get_height() / 2),
            self.game.player.hero.lanturn_strength,
        )

        light_surf_pil = Image.frombytes(
            "RGBA",
            (light_surf.get_width(), light_surf.get_height()),
            pygame.image.tostring(light_surf, "RGBA", False),
        )
        light_surf_blur = light_surf_pil.filter(ImageFilter.GaussianBlur(radius=100))
        light_surf = pygame.image.fromstring(
            light_surf_blur.tobytes(),
            (light_surf.get_width(), light_surf.get_height()),
            "RGBA",
        ).convert_alpha()

        pygame.draw.circle(
            light_surf,
            (255, 250, 205),
            (light_surf.get_width() / 2, light_surf.get_height() / 2),
            self.game.player.hero.lanturn_strength,
        )

        light_surf_pil = Image.frombytes(
            "RGBA",
            (light_surf.get_width(), light_surf.get_height()),
            pygame.image.tostring(light_surf, "RGBA", False),
        )
        light_surf_blur = light_surf_pil.filter(ImageFilter.GaussianBlur(radius=50))
        light_surf = pygame.image.fromstring(
            light_surf_blur.tobytes(),
            (light_surf.get_width(), light_surf.get_height()),
            "RGBA",
        ).convert_alpha()

        pygame.draw.circle(
            light_surf,
            (255, 250, 205),
            (light_surf.get_width() / 2, light_surf.get_height() / 2),
            self.game.player.hero.lanturn_strength,
        )

        light_surf_pil = Image.frombytes(
            "RGBA",
            (light_surf.get_width(), light_surf.get_height()),
            pygame.image.tostring(light_surf, "RGBA", False),
        )
        light_surf_blur = light_surf_pil.filter(ImageFilter.GaussianBlur(radius=20))
        light_surf = pygame.image.fromstring(
            light_surf_blur.tobytes(),
            (light_surf.get_width(), light_surf.get_height()),
            "RGBA",
        ).convert_alpha()

        self.light_surf = light_surf
        self.light_surf.set_colorkey((0, 0, 0))

        self.lights = {
            deg: pygame.transform.rotate(self.light_surf, deg - 90)
            for deg in range(-360, 360, 20)
        }

        for deg, light in self.lights.items():
            pygame.image.save(light, f"lights/light-{deg}.png")

    def render(self):
        self.surf.fill((0, 0, 0))
        mx, my = pygame.mouse.get_pos()
        v = pygame.math.Vector2(
            mx - self.game.player.hero.x, my - self.game.player.hero.y
        )
        v.scale_to_length(self.game.player.hero.flashlight_strength)
        self.game.player.hero.flashlight_angle = v.angle_to(pygame.math.Vector2(1, 0))

        for other in self.game.player.others.__root__:
            if other.id == self.game.player.hero.id:
                continue

            light_index = list(self.lights.keys())[
                bisect.bisect_left(
                    list(self.lights.keys()),
                    other.flashlight_angle + 90,
                )
            ]

            my_light = self.lights[light_index]
            self.surf.blit(
                my_light,
                (
                    other.x - my_light.get_width() / 2,
                    other.y - my_light.get_height() / 2,
                ),
            )

        light_index = list(self.lights.keys())[
            bisect.bisect_left(
                list(self.lights.keys()),
                self.game.player.hero.flashlight_angle + 90,
            )
        ]

        my_light = self.lights[light_index]
        self.surf.blit(
            my_light,
            (
                self.game.player.hero.x - my_light.get_width() / 2,
                self.game.player.hero.y - my_light.get_height() / 2,
            ),
        )

        # for r in range(-25, 25):
        #     _v = v.rotate(r)
        #     pygame.draw.line(
        #         self.surf,
        #         (255, 250, 205),
        #         (self.game.player.hero.x, self.game.player.hero.y),
        #         (self.game.player.hero.x + _v.x, self.game.player.hero.y + _v.y),
        #         50,
        #     )
        # # draw a circle
        # pygame.draw.circle(
        #     self.surf,
        #     (255, 250, 205),
        #     (self.game.player.hero.x, self.game.player.hero.y),
        #     self.game.player.hero.lanturn_strength,
        # )

        # for other in self.game.player.others.__root__:
        #     if other.id == self.game.player.hero.id:
        #         continue
        #     v = pygame.math.Vector2(0, 1)
        #     v = v.rotate(-other.flashlight_angle)
        #     v.scale_to_length(other.flashlight_strength)
        #     for r in range(-25, 25):
        #         _v = v.rotate(r)
        #         pygame.draw.line(
        #             self.surf,
        #             (255, 250, 205),
        #             (other.x, other.y),
        #             (other.x + _v.x, other.y + _v.y),
        #             50,
        #         )
        #     pygame.draw.circle(
        #         self.surf,
        #         (255, 250, 205),
        #         (other.x, other.y),
        #         other.lanturn_strength,
        #     )

        self.game.darkness.blit(
            self.surf,
            (0, 0),
        )
