# Copyright 2021-2024 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only

import importlib.resources as resources
from datetime import datetime

import gi

from .dataframe import DataFrame
from .util import bearing_to_arrow, have_touchscreen
from .widgets import text_barchart

gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Adw, GLib, Gtk  # noqa: E402, I100

respath = __name__.split(sep='.')[0]


@Gtk.Template(string=resources.read_text(respath, 'window.ui'))
class Window(Adw.ApplicationWindow):

    __gtype_name__ = "Window"

    toast_overlay = Gtk.Template.Child()

    carousel = Gtk.Template.Child()
    page1 = Gtk.Template.Child()
    page2 = Gtk.Template.Child()

    dataview = Gtk.Template.Child()
    dataheader = Gtk.Template.Child()
    app_menubutton = Gtk.Template.Child()
    datascroll = Gtk.Template.Child()
    datascroll_h = Gtk.Template.Child()
    frameclamp = Gtk.Template.Child()
    infocarousel = Gtk.Template.Child()
    chartlabel = Gtk.Template.Child()
    speedlabel = Gtk.Template.Child()
    recording_box = Gtk.Template.Child()
    recording_label = Gtk.Template.Child()

    loglabel = Gtk.Template.Child()

    def __init__(self, app):
        super().__init__(application=app, title=GLib.get_application_name())

        self.app = app

        self.builder = Gtk.Builder()
        self.builder.add_from_string(resources.read_text(respath, 'menus.ui'))

        self.app_menubutton.set_menu_model(self.builder.get_object('app-menu'))

        self.dataframe = DataFrame()
        self.dataframe.header.set_visible(False)
        self.frameclamp.set_child(self.dataframe)
        self.sensitive(False)

        # recording_box top or bottom
        self.rec_on_top = False

        if have_touchscreen():
            self.datascroll.connect('edge-overshot', self.on_edge_overshot)
        else:
            # This enables touchpad scolling on main Carousel
            self.datascroll.set_policy(Gtk.PolicyType.NEVER,
                                       Gtk.PolicyType.AUTOMATIC)
            self.datascroll_h.set_policy(Gtk.PolicyType.NEVER,
                                         Gtk.PolicyType.AUTOMATIC)

        # Bar chart heights
        self.chart_small = 10
        self.chart_large = 30
        self.chart_size = self.chart_small

        self.set_barchart({'visibles': [], 'actives': []})
        self.set_speedlabel(None)

        click = Gtk.GestureClick.new()
        click.set_button(0)
        click.set_touch_only(False)
        self.infocarousel.add_controller(click)
        click.connect("released", self.on_infocarousel_released)

    def log_msg(self, text):
        maxlines = 100  # Maximum num of lines in GtkLabel
        msg = datetime.now().strftime("[%H:%M:%S] ") + text
        text = self.loglabel.get_text().split('\n')
        if len(text) > maxlines:
            text = text[1:]
        text.append(msg)
        self.loglabel.set_text("\n".join(text))
        print(msg)

    def set_speedlabel(self, speed, bearing=None):
        spd = str(int(3.6 * speed)) if speed else "-"
        arrow = bearing_to_arrow(bearing) if bearing is not None else ""
        speedfmt = '<span size="50000">%s</span>\n<span size="30000">%s</span>'
        speedstr = (speedfmt % (spd + arrow, "km/h") if speed else
                    speedfmt % ('-', ' '))
        self.speedlabel.set_markup(speedstr)

    def on_edge_overshot(self, scrolledwindow, pos):
        if pos == Gtk.PositionType.TOP:
            self.app_menubutton.get_popover().popup()

    def sensitive(self, sensitive):
        self.chartlabel.set_sensitive(sensitive)
        self.speedlabel.set_sensitive(sensitive)
        self.dataframe.grid.set_sensitive(sensitive)

    def start_recording(self):
        self.recording_label.set_markup("Warming up...")
        self.recording_box.set_visible(True)
        if self.rec_on_top:
            self.dataview.set_top_bar_style(Adw.ToolbarStyle.RAISED)
        else:
            self.dataview.set_reveal_bottom_bars(True)

    def stop_recording(self):
        self.dataview.set_reveal_bottom_bars(False)
        self.dataview.set_top_bar_style(Adw.ToolbarStyle.FLAT)
        self.recording_box.set_visible(False)

    @Gtk.Template.Callback()
    def carousel_forward_cb(self, button):
        self.carousel.scroll_to(self.page2, True)

    @Gtk.Template.Callback()
    def carousel_back_cb(self, button):
        self.carousel.scroll_to(self.page1, True)

    @Gtk.Template.Callback()
    def recording_to_top(self, bpoint):
        if not self.rec_on_top:
            self.rec_on_top = True
            self.dataview.remove(self.recording_box)
            self.dataview.set_reveal_bottom_bars(False)
            self.dataheader.pack_start(self.recording_box)
            self.recording_box.set_margin_top(0)
            self.recording_box.set_margin_bottom(0)
            if self.app.gpx is not None:  # Recording is on
                self.dataview.set_top_bar_style(Adw.ToolbarStyle.RAISED)
        return False

    @Gtk.Template.Callback()
    def recording_to_bottom(self, bpoint):
        if self.rec_on_top:
            self.rec_on_top = False
            self.dataheader.remove(self.recording_box)
            self.dataview.add_bottom_bar(self.recording_box)
            self.dataview.set_top_bar_style(Adw.ToolbarStyle.FLAT)
            self.recording_box.set_margin_top(8)
            self.recording_box.set_margin_bottom(8)
            if self.app.gpx is not None:  # Recording is on
                self.dataview.set_reveal_bottom_bars(True)
        return False

    @Gtk.Template.Callback()
    def infocarousel_page_changed_cb(self, carousel, index):
        if index == 1 and self.chart_size == self.chart_large:
            self.chart_size = self.chart_small
            self.set_barchart(self.app.last_data)
        return False

    def set_barchart(self, data):
        if data is None:
            return ''
        barchart = text_barchart(
            ((e['prn'], e['snr']) for e in data['visibles']),
            data['actives'], height=self.chart_size)
        self.chartlabel.set_markup("<tt>" + barchart + "</tt>")
        return barchart

    def on_infocarousel_released(self, gesture, n_press, x, y):
        if n_press != 1 or self.infocarousel.get_position() > 0.5:
            return
        self.chart_size = (self.chart_small if self.chart_size == self.chart_large
                           else self.chart_large)
        self.set_barchart(self.app.last_data)
