# -*- coding: utf-8 -*-
import gi
import logging
import os

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GdkPixbuf, Gio, GLib, Pango

klipperscreendir = os.getcwd()

class KlippyGtk:
    labels = {}
    font_ratio = [43, 29]
    keyboard_ratio = .22
    width_ratio = 16
    height_ratio = 9.375

    def __init__(self, screen, width, height, theme, cursor, fontsize_type):
        self.screen = screen
        self.width = width
        self.height = height
        self.theme = theme
        self.font_size = int(min(
            self.width / self.font_ratio[0],
            self.height / self.font_ratio[1]
        ))
        if fontsize_type == "small":
            self.font_size = round(self.font_size * 0.91)
        elif (fontsize_type == "large"):
            self.font_size = round(self.font_size * 1.09)
        self.header_size = int(round((self.width / self.width_ratio) / 1.33))
        self.img_width = int(round(self.width / self.width_ratio))
        self.img_height = int(round(self.height / self.height_ratio))
        self.action_bar_width = int(self.width * .1)
        self.header_image_scale_width = 1.2
        self.header_image_scale_height = 1.4
        self.cursor = cursor

        logging.debug("img width: %s height: %s" % (self.img_width, self.img_height))

    def get_action_bar_width(self):
        return self.action_bar_width

    def get_content_width(self):
        return self.width - self.action_bar_width

    def get_content_height(self):
        return self.height - self.header_size

    def get_font_size(self):
        return self.font_size

    def get_header_size(self):
        return self.header_size

    def get_header_image_scale(self):
        return [self.header_image_scale_width, self.header_image_scale_height]

    def get_image_width(self):
        return self.img_width

    def get_image_height(self):
        return self.img_height

    def get_keyboard_height(self):
        return (self.width - self.get_action_bar_width()) * self.keyboard_ratio

    def Label(self, label, style=None):
        la = Gtk.Label(label)
        if style is not None and style is not False:
            la.get_style_context().add_class(style)
        return la

    def ImageLabel(self, image_name, text, size=20, style=False, width_scale=.32, height_scale=.32):
        box1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15)
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            "%s/styles/%s/images/%s.svg" % (klipperscreendir, self.theme, str(image_name)),
            int(round(self.img_width * width_scale)), int(round(self.img_height * height_scale)), True)

        image = Gtk.Image.new_from_pixbuf(pixbuf)

        label = Gtk.Label()
        label.set_text(text)
        box1.add(image)
        box1.add(label)

        if style is not False:
            ctx = box1.get_style_context()
            ctx.add_class(style)

        return {"l": label, "b": box1}

    def Image(self, image_name, style=False, width_scale=1, height_scale=1):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            "%s/styles/%s/images/%s" % (klipperscreendir, self.theme, str(image_name)),
            int(round(self.img_width * width_scale)), int(round(self.img_height * height_scale)), True)

        return Gtk.Image.new_from_pixbuf(pixbuf)

    def ImageFromFile(self, filename, style=False, width_scale=1, height_scale=1):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            filename, int(round(self.img_width * width_scale)), int(round(self.img_height * height_scale)), True)

        return Gtk.Image.new_from_pixbuf(pixbuf)

    def PixbufFromFile(self, filename, style=False, width_scale=1, height_scale=1):
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            filename, int(round(self.img_width * width_scale)), int(round(self.img_height * height_scale)), True)

        return pixbuf

    def PixbufFromHttp(self, resource, style=False, width_scale=1, height_scale=1):
        response = self.screen.apiclient.get_thumbnail_stream(resource)
        if response is False:
            return None
        stream = Gio.MemoryInputStream.new_from_data(response, None)
        pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(
            stream, int(round(self.img_width * width_scale)), int(round(self.img_height * height_scale)), True)

        return pixbuf

    def ProgressBar(self, style=False):
        bar = Gtk.ProgressBar()

        if style is not False:
            ctx = bar.get_style_context()
            ctx.add_class(style)

        return bar

    def Button(self, label=None, style=None):
        b = Gtk.Button(label=label)
        b.set_hexpand(True)
        b.set_vexpand(True)
        b.set_can_focus(False)
        b.props.relief = Gtk.ReliefStyle.NONE

        if style is not None:
            b.get_style_context().add_class(style)

        return b

    def ButtonImage(self, image_name, label=None, style=None, width_scale=1.38, height_scale=1.38,
                    position=Gtk.PositionType.TOP, word_wrap=True):
        filename = "%s/styles/%s/images/%s.svg" % (klipperscreendir, self.theme, str(image_name))
        if not os.path.exists(filename):
            logging.error("Unable to find button image (theme, image): (%s, %s)" % (self.theme, str(image_name)))
            filename = "%s/styles/%s/images/%s.svg" % (klipperscreendir, self.theme, "warning")

        b = Gtk.Button(label=label)

        if os.path.exists(filename):
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                filename,
                int(round(self.img_width * width_scale)),
                int(round(self.img_height * height_scale)),
                True
            )
            img = Gtk.Image.new_from_pixbuf(pixbuf)
            b.set_image(img)

        b.set_hexpand(True)
        b.set_vexpand(True)
        b.set_can_focus(False)
        b.set_image_position(position)
        b.set_always_show_image(True)
        b.props.relief = Gtk.ReliefStyle.NONE

        if word_wrap is True:
            try:
                # Get the label object
                child = b.get_children()[0].get_children()[0].get_children()[1]
                child.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR)
                child.set_line_wrap(True)
            except Exception:
                pass

        if style is not None:
            b.get_style_context().add_class(style)

        return b

    def Dialog(self, screen, buttons, content, callback=None, *args):
        dialog = Gtk.Dialog()
        dialog.set_default_size(screen.width, screen.height)
        dialog.set_resizable(False)
        dialog.set_transient_for(screen)
        dialog.set_modal(True)

        for button in buttons:
            dialog.add_button(button_text=button['name'], response_id=button['response'])

        dialog.connect("response", callback, *args)
        dialog.get_style_context().add_class("dialog")

        box = Gtk.Box()
        box.set_size_request(screen.width - 60, 0)
        box.set_vexpand(True)

        content_area = dialog.get_content_area()
        content_area.set_margin_start(15)
        content_area.set_margin_end(15)
        content_area.set_margin_top(15)
        content_area.set_margin_bottom(15)
        content_area.add(content)

        dialog.show_all()
        # Change cursor to blank
        if self.cursor:
            dialog.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW))
        else:
            dialog.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.BLANK_CURSOR))

        return dialog


    def ToggleButtonImage(self, image_name, label, style=False, width_scale=1.38, height_scale=1.38):
        filename = "%s/styles/%s/images/%s.svg" % (klipperscreendir, self.theme, str(image_name))
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            filename,
            int(round(self.img_width * width_scale)),
            int(round(self.img_height * height_scale)),
            True
        )

        img = Gtk.Image.new_from_pixbuf(pixbuf)

        b = Gtk.ToggleButton(label=label)
        b.set_image(img)
        b.set_hexpand(True)
        b.set_vexpand(True)
        b.set_can_focus(False)
        b.set_image_position(Gtk.PositionType.TOP)
        b.set_always_show_image(True)
        b.props.relief = Gtk.ReliefStyle.NONE

        if style is not False:
            ctx = b.get_style_context()
            ctx.add_class(style)

        return b

    def HomogeneousGrid(self, width=None, height=None):
        g = Gtk.Grid()
        g.set_row_homogeneous(True)
        g.set_column_homogeneous(True)
        if width is not None and height is not None:
            g.set_size_request(width, height)
        return g

    def ToggleButton(self, text):
        b = Gtk.ToggleButton(text)
        b.props.relief = Gtk.ReliefStyle.NONE
        b.set_hexpand(True)
        b.set_vexpand(True)
        return b

    def formatFileName(self, name):
        name = name.split('/')[-1] if "/" in name else name
        name = name.split('.gcod')[0] if ".gcode" in name else name
        if len(name) > 25:
            return name[0:25] + "\n" + name[25:50]
        return name


    def formatTimeString(self, seconds):
        time = int(seconds)
        text = ""
        if int(time/3600) != 0:
            text += str(int(time/3600))+"h "
        text += str(int(time/60) % 60)+"m "+str(time % 60)+"s"
        return text

    def formatTemperatureString(self, temp, target):
        if (target > temp-2 and target < temp+2) or round(target, 0) == 0:
            return str(round(temp, 1)) + "°C"  # °C →"
        return str(round(temp)) + " → " + str(round(target)) + "°C"
