#!~/.pyenv/versions/3.11.6/bin/python
#
# Copyright (c) 2024 Cutieguwu | Olivia Brooks
#
# -*- coding:utf-8 -*-
# @Title: Interface Items.
# @Author: Cutieguwu | Olivia Brooks
# @Email: owen.brooks77@gmail.com | obroo2@ocdsb.ca
# @Description: Interface items for menus and scenes in a pygame game.
#
# @Script: interface.py
# @Date Created: 22 Mar, 2024
# @Last Modified: 13 Jun, 2024
# @Last Modified by: Cutieguwu | Olivia Brooks
# ----------------------------------------------------------

import pygame
from lib.system import FEATURES


class Button():
    """
    Creates a button on a window.
    """

    def __init__(self, game, name, x, y, image_neutral, image_hover, function, args=None):
        self.TYPE = "button"

        width = image_neutral.get_width()                                               # Can use neutral image as all images should have identical sizes.
        height = image_neutral.get_height()

        self.GAME = game
        self.WINDOW = self.GAME.WINDOW
        scale = self.GAME.SCALE.scaleUi

        self.function = function
        self.functionArgs = args

        self.ID = name

        self.IMAGES = {
            "neutral": pygame.transform.scale(image_neutral, (width * scale, height * scale)),
            "hover": pygame.transform.scale(image_hover, (width * scale, height * scale))
        }

        Interface_Functions.convert_images(self)

        self.rect = self.IMAGES["neutral"].get_rect()
        self.rect.topleft = (x * scale, y * scale)

        # Cannot overwrite rect.collidepoint with Interface_Functions.collidepoint.

        self.time_delay = 0

        self.GAME.gameInteractables.append(self)                                        # Add to button to refresh.

    def draw(self):
        """
        Draws button on screen.
        """

        Interface_Functions.draw(self)
    
    def is_hovered(self):
        """
        Checks if button is hovered.
        """

        return Interface_Functions.collidepoint(self, pygame.mouse.get_pos())

    def remove(self):
        """
        Clears button from screen.
        """

        Interface_Functions.destroy(self)

class Progress_bar():
    """
    Creates a progress bar that updates based on a scale.
    """

    def __init__(self, game, x, y, barWidth:int, bobberImages:list, barImageLeft, barImageRight, barImageClear, barImageFill):
        """
        x: distance in percent from window origin.
        y: distance in percent from window origin.
        barWidth: Percent of window width filled.
        """

        self.GAME = game
        self.WINDOW = self.GAME.WINDOW

        self.x = (x / 100) * self.WINDOW.width
        self.y = (y / 100) * self.WINDOW.height

        for image in bobberImages:
            image.convert_alpha()

        self.bobberImages = bobberImages

        self.barImages = {
            "left": barImageLeft.convert_alpha(),
            "right": barImageRight.convert_alpha(),
            "clear": barImageClear.convert_alpha(),
            "fill": barImageFill.convert_alpha()
        }

        self.bobberState = 0
        self.bobberStateRange = len(bobberImages)

        self.widthLeft = self.barImages["left"].get_width()
        self.widthRight = self.barImages["right"].get_width()

        self.barFillWidth = int("%.0f" % ((self.WINDOW.width * (barWidth / 100)) - (self.widthLeft + self.widthRight)))

        self.barHeight = self.barImages["left"].get_height()
        self.bobberHeight = self.bobberImages[self.bobberState].get_height()

        self.barCenterOffset = (self.barHeight / 2) - (self.barImages["clear"].get_height() / 2)

        self.bobberTimer = 0

    def draw(self, rangeComplete, rangeTotal, framerate=30):

        self.bobberTimer = self.bobberTimer + 1

        rangeComplete = int("%.0f" % (rangeComplete * self.barFillWidth / rangeTotal))

        self.WINDOW.window.blit(self.barImages["left"], (self.x, self.y))
        self.WINDOW.window.blit(self.barImages["right"], (self.x + self.widthLeft + self.barFillWidth, self.y))

        for i in range(0, rangeComplete):
            self.WINDOW.window.blit(self.barImages["fill"], (self.x + self.widthLeft + i, self.y + self.barCenterOffset))

        for i in range(rangeComplete, self.barFillWidth):
            self.WINDOW.window.blit(self.barImages["clear"], (self.x + self.widthLeft + i, self.y + self.barCenterOffset))

        if (self.bobberTimer / framerate) > 0.25:
            self.bobberTimer = 0
            if self.bobberState == self.bobberStateRange - 1:
                self.bobberState = 0
            else:
                self.bobberState = self.bobberState + 1
        
        self.WINDOW.window.blit(self.bobberImages[self.bobberState], (self.x + rangeComplete, self.y - (self.bobberHeight / 2)))

class Checkbox():
    """
    Creates a Checkbox on a window.
    """

    def __init__(self, game, name, x, y, image_neutral, image_hover, image_active, condition, function=None, args=None):
        self.TYPE = "checkbox"

        width = image_neutral.get_width()                                               # Can use neutral image as all images should have identical sizes.
        height = image_neutral.get_height()

        self.GAME = game
        self.WINDOW = self.GAME.WINDOW
        scale = self.GAME.SCALE.scaleUi

        self.function = function
        self.functionArgs = args

        self.ID = name

        self.IMAGES = {
            "neutral": pygame.transform.scale(image_neutral, (width * scale, height * scale)),
            "hover": pygame.transform.scale(image_hover, (width * scale, height * scale)),
            "active": pygame.transform.scale(image_active, (width * scale, height * scale))
        }

        Interface_Functions.convert_images(self)

        self.rect = self.image_neutral.get_rect()
        self.rect.topleft = (x * scale, y * scale)

        self.time_delay = 0

        self.condition = condition

        self.GAME.gameInteractables.append(self)                                        # Add to checkbox to refresh.

    def draw(self):
        """
        Draws checkbox on screen.
        """

        Interface_Functions.draw(self)
    
    def is_hovered(self):
        """
        Checks if checkbox is hovered.
        """

        return Interface_Functions.is_hovered(self)

    def remove(self):
        """
        Clears checkbox from screen.
        """

        Interface_Functions.destroy(self)


class Interface_Functions():
    """
    All functions called by interface objects.
    """

    def __init__(self, game):
        self.GAME = game

    def convert_images(object):
        """
        Converts the object's images to pygame format increasing performance.
        """

        temp = {}

        for image in object.IMAGES.items():
            temp[image[0]] = image[1].convert_alpha()
        
        object.IMAGES = temp

    def destroy(object):
        """
        Destroys the interface object.
        """

        temp = []

        for interactable in object.GAME.gameInteractables:
            if interactable != object:
                temp.append(interactable)
        
        object.GAME.gameInteractables = temp

        del object

    def draw(object):
        """
        Draws interface object.
        """

        if object.TYPE == "checkbox" and object.condition():
            object.WINDOW.window.blit(object.IMAGES["active"], (object.rect.x, object.rect.y))
        elif object.is_hovered():
            object.WINDOW.window.blit(object.IMAGES["hover"], (object.rect.x, object.rect.y))
        else:
            object.WINDOW.window.blit(object.IMAGES["neutral"], (object.rect.x, object.rect.y))

    def enter_fullscreen(self):
        """
        Enters Fullscreen if possible.
        """

        if self.GAME.WINDOW.toggle_fullscreen():
            FEATURES["Fullscreen"]["is_active"] = True

    def exit_to_desktop(self):

        self.GAME.levelOn = False
        self.GAME.menuOn = False
        self.GAME.sceneOn = False
        self.GAME.gameOn = False

    def collidepoint(object, coords:tuple):
        """
        Rewritten version of pygame rect.collidepoint.
        """

        x, y, width, height = object.rect
        dx = width + x
        dy = height + y


        if coords[0] in range(x, dx + 1) and coords[1] in range(y, dy + 1):
            return True
        else:
            return False

    def is_hovered(object):
        """
        Checks if mouse is hovering interface object.
        """

        return Interface_Functions.collidepoint(object, pygame.mouse.get_pos())

    def return_to_game(self):
        """
        Exits a pause state.
        """

        for button in self.GAME.LEVEL.layout.INTERACTABLES:
            button.remove()

        self.GAME.menuOn = False

        self.GAME.LEVEL.load_level_state()