#!/usr/bin/python
#  -*- coding: utf-8 -*-
import pygame.freetype
import pygame
import os
import math
import datetime
import glob
from time import time
from .toolkit import *
from .aspect_scale import *
from .gradient import *
from time import time, sleep


class Gui:
    def __init__(self, display_resolution, fg_color, bg_color,
                 cursor_visible, quit_function):
        pygame.init()
        pygame.mixer.quit()
        # a fullscreen switch for debugging purposes
        self.fullscreen = True 
        # the display resolution as a tuple
        self.display_size = (int(display_resolution.split(
            ',')[0]), int(display_resolution.split(',')[0]))
        # colors for foreground and background
        self.fg_color = self.string_to_color(fg_color)
        self.bg_color = self.string_to_color(bg_color)
        # the window size if the program is not set for fullscreen and no resolution was set
        self.window_size = (800, 480)
        # should the mouse cursor be visible?
        if cursor_visible != "1": pygame.mouse.set_cursor((8,8),(0,0),(0,0,0,0,0,0,0,0),(0,0,0,0,0,0,0,0))
        # correction factor for text elements
        # variables for resource files
        self.resource_path = "assets/"
        # quit function
        self.quit_function = quit_function

        self.wallpaper_path = "."
        self.show_wallpaper = True

        self.basefont_file = self.resource_path + "SourceSansPro-Regular.otf"
        self.boldfont_file = self.resource_path + "SourceSansPro-Semibold.otf"
        self.logo_image = self.resource_path + "alarm-clock.png"
        self.image_cache = {}
        self.elements = []
        # start the gui
        self.set_window_details()
        self.display_init()
        self.calculate_base_sizes()

        self.old_time = 0
        self.fps_counter = 1
        self.target_framerate = 30

        self.clock = pygame.time.Clock()
        self.dblclktime = 200
        self.clicktime = 0
        self.await_dblclk = False
        self.clickEvent = None
        self.click = None
        self.redraw = True

    # initialize the display surface
    def display_init(self):
        # try to create a surface and check if it fails
        try:
            # fullscreen is the default
            if self.fullscreen:
                # create a hardware accelerated fullscreen surface
                self.display_surface = pygame.display.set_mode(
                    self.display_size, pygame.FULLSCREEN)
            # alternatively try a windowed surface
            else:
                self.display_surface = pygame.display.set_mode(size=self.window_size,
                                                               flags=pygame.RESIZABLE, display=1)
        except Exception as exc:
            print(exc)
            print("Display initialization failed. This program needs a running X-Server.")
            exit()

        self.loadImageCache()
        # get absolute size of the surface independend from what was
        # requested.
        self.display_size = self.display_surface.get_size()

        self.current_wallpaper_surface = pygame.image.load(
            self.wallpaper_path + "/wallpaper.jpg")
        self.current_wallpaper_surface = aspect_scale(
            self.current_wallpaper_surface, self.display_size).convert()

    def loadImageCache(self):
        image_list = glob.glob(self.resource_path+'/*.png')
        for image in image_list:
            path, filename = os.path.split(image)
            self.image_cache[filename] = pygame.image.load(
                image).convert_alpha()

    def display_resize(self):
        self.display_init()
        self.calculate_base_sizes()

    # set the window caption and the icon
    def set_window_details(self):
        pygame.display.set_caption("c't Radio Alarm Clock")
        icon = pygame.image.load(self.logo_image)
        pygame.display.set_icon(icon)

    def calculate_base_sizes(self):
        # calculate the sizes of displayed elements based on the available
        # display resolution.
        # the size of the titlebar is an essential measurement and determines
        # most other measurements
        self.basefont_size = self.display_size[0] / 30
        pass

    def calculate_object_size(self, width_percentage, height_percentage):
        width = math.floor(self.display_size[0] * width_percentage / 100)
        height = math.floor(self.display_size[1] * height_percentage / 100)

        return (width, height)

    def calculate_position(self, percentage, surface, origin_v="top", origin_h="left"):
        surface_size = surface.get_size()
        origin_shift_x = 0
        origin_shift_y = 0
        if origin_v == "center":
            origin_shift_y = (
                self.display_size[1] / 2) - (surface_size[1] / 2)
        elif origin_v == "bottom":
            origin_shift_y = self.display_size[1] - surface_size[1]

        if origin_h == "center":
            origin_shift_x = (
                self.display_size[0] / 2) - (surface_size[0] / 2)
        elif origin_h == "right":
            origin_shift_x = self.display_size[0] - surface_size[0]
        top_pos = ((percentage[0] / 100) *
                   self.display_size[0]) + origin_shift_y
        left_pos = ((percentage[1] / 100) *
                    self.display_size[1]) + origin_shift_x
        return (left_pos, top_pos)

    def calculate_font_size(self, percentage):
        fontsize = tuple((percentage / 100) * x for x in self.display_size)
        return fontsize[0]

    # refresh the display

    def update(self):
        self.process_events()
        # paint the background color or wallpaper
        if not self.show_wallpaper:
            self.display_surface.fill(self.bg_color)
        else:
            self.display_surface.blit(self.current_wallpaper_surface, (0, 0))
        # iterate all surfaces and paint them
        rects = []
        for element in self.elements:
            image_pos_x = element.Position[0]
            image_pos_y = element.Position[1]
            rects.append(element.Rect)

            self.display_surface.blit(
                element.Surface, (image_pos_x, image_pos_y))
        # flip the screen for a refreh
        if self.redraw:
            pygame.display.update()
            self.redraw = False
        else:
            pygame.display.update(rects)
        # self.show_fps()
        self.clock.tick(self.target_framerate)

    def show_fps(self):
        new_time = int(time())
        if new_time != self.old_time:
            print("FPS:" + str(int(self.clock.get_fps())))
            self.old_time = new_time

    def quit(self):
        # cleanly deactivate the pygame instance
        self.quit_function()

    # process all received events

    def process_events(self):
        clicked = False
        events = pygame.event.get()
        for event in events:
            # if the event is any type of quit request end the program
            if event.type == pygame.QUIT:
                quit()

            # resize the window if its requested
            elif event.type == pygame.VIDEORESIZE:
                self.window_size = event.size
                self.display_resize()

            # evaluate keypresses
            elif event.type == pygame.KEYDOWN:
                # exit on Escape
                if event.key == pygame.K_ESCAPE:
                    quit()
                # switch to fullscreen on F11
                elif event.key == pygame.K_F11:
                    self.fullscreen = not self.fullscreen

            # evaluate all presses of the left mousebutton
            elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                clicked = True
                self.clicktime = pygame.time.get_ticks()
                self.clickEvent = event

        click = None
        timediff = pygame.time.get_ticks() - self.clicktime
        if clicked and self.await_dblclk == False and self.click is None:
            self.await_dblclk = True
            pass
        elif clicked and timediff < self.dblclktime and self.await_dblclk:
            click = "double"
            self.await_dblclk = False
        elif timediff > self.dblclktime and self.await_dblclk:
            click = "single"
            self.await_dblclk = False
        if click != None:
            self.await_dblclk = False
            self.clicktime = 0
            for element in self.elements:
                if hasattr(element, 'Callback') and element.Callback != None and element.Rect.collidepoint(self.clickEvent.pos):
                    if click == "double" and element.DblclkCallback != None:
                        element.DblclkCallback()
                    else:
                        element.Callback()

    # exit the programm

    def shutdown(self):
        # call(["sudo", "poweroff"])
        self._running = False

    # convert a given comma seperated string to a color object

    def string_to_color(self, string):
        # split the string into a list
        list = string.split(',')
        # create color from the list indices
        color = pygame.Color(
            int(list[0]),
            int(list[1]),
            int(list[2])
        )
        # return the created color object
        return color


if __name__ == "__main__":
    print("This module cannot be called directly.")