from typing import Optional
from gi.repository import Gdk, Gio, GLib, Gtk, GObject, Pango, Adw
from datetime import datetime
from gettext import gettext as _

class ActivitySummary(GObject.Object):
    name: str = "activity"
    seconds: int = 0

    def __init__(self, name="activity", seconds=0):
        super().__init__()
        self.name = name
        self.seconds = seconds

    @property
    def full_time(self):
        if not self.seconds:
            return (0, 0, 0)

        m = self.seconds // 60
        s = self.seconds % 60
        h = m // 60
        m = m % 60

        return (h, m, s)


class ActivitySummaryWidget(Gtk.Box):
    name_label = NotImplemented
    time_label = NotImplemented

    summary = NotImplemented

    def __init__(self, summary):
        super().__init__(orientation=Gtk.Orientation.HORIZONTAL)
        self.summary = summary
        time = "{:02d}:{:02d}:{:02d}".format(*summary.full_time)

        self.name_label = Gtk.Label(label=summary.name)
        self.time_label = Gtk.Label(label=time)
        self.name_label.set_margin_start(6)
        self.name_label.set_xalign(0.0)
        self.name_label.set_hexpand(True)
        self.name_label.set_ellipsize(Pango.EllipsizeMode.END)
        self.name_label.set_selectable(True)
        self.time_label.set_xalign(1.0)
        self.time_label.set_selectable(True)
        self.time_label.set_margin_end(6)

        self.prepend(self.name_label)
        self.append(self.time_label)

        self.show()


class Activity(GObject.Object):
    name: str = "activity"
    start: datetime = datetime.now()
    stop: Optional[datetime] = None
    id: Optional[int] = None
    comments: Optional[str] = None

    def __init__(self, name="activity", start=datetime.now(),
                 stop=None, id=None, comments=None):
        super().__init__()
        self.name = name
        self.start = start
        self.stop = stop
        self.id = id
        self.comments = comments or ""

    @property
    def seconds(self):
        if not self.stop:
            return 0
        return int((self.stop - self.start).total_seconds())

    @property
    def full_time(self):
        if not self.stop:
            return (0, 0, 0)

        m = self.seconds // 60
        s = self.seconds % 60
        h = m // 60
        m = m % 60

        return (h, m, s)

    @property
    def start_time(self):
        if not self.start:
            return (0, 0)

        return (self.start.hour, self.start.minute)

    @property
    def end_time(self):
        if not self.stop:
            return (0, 0)

        return (self.stop.hour, self.stop.minute)


class ActivityWidget(Adw.ActionRow):
    label = NotImplemented
    duration_label = NotImplemented
    start_label = NotImplemented
    comments = NotImplemented
    activity = NotImplemented

    activity_id = None

    def __init__(self, act):
        super().__init__()

        #Set the activity (and id)
        self.activity = act
        if act.id:
            self.activity_id = act.id

        # Setting the title of the raw
        self.props.title = act.name
        # Setting the subtitle of the raw to comments
        self.props.subtitle = act.comments

        # Creating the duration label
        self.duration_label = Gtk.Label()
        self.duration_label.set_markup(self.create_duration_string())
        context = self.duration_label.get_style_context()
        context.add_class("dim-label")

        if not self.activity.stop:
            self.get_style_context().add_class("not-ended")

        # Adding the duration label to the raw
        self.add_suffix(self.duration_label)

        # Menu model
        model = Gio.Menu()

        # First part of the menu
        actions_model = Gio.Menu()

        if not self.activity.stop:
            # Add continue button
            item = Gio.MenuItem()
            item.set_label(_("Continue activity"))
            item.set_action_and_target_value("app.continue", GLib.Variant("i", act.id))
            actions_model.append_item(item)

        # Add remove button
        item = Gio.MenuItem()
        item.set_label(_("Remove activity"))
        item.set_action_and_target_value("app.remove", GLib.Variant("i", act.id))
        actions_model.append_item(item)

        # Add edit button
        item = Gio.MenuItem()
        item.set_label(_("Edit activity"))
        item.set_action_and_target_value("app.edit", GLib.Variant("i", act.id))
        actions_model.append_item(item)

        # Second part of the menu
        copy_model = Gio.Menu()

        # Add copy title button
        item = Gio.MenuItem()
        item.set_label(_("Copy title"))
        item.set_action_and_target_value("app.copy-text", GLib.Variant("s", act.name))
        copy_model.append_item(item)

        # Add copy comments button
        item = Gio.MenuItem()
        item.set_label(_("Copy comments"))
        item.set_action_and_target_value("app.copy-text", GLib.Variant("s", act.comments))
        copy_model.append_item(item)

        # Append sections
        model.append_section(None, actions_model)
        model.append_section(None, copy_model)

        # Add popover with the menu
        popover = Gtk.PopoverMenu.new_from_model(model)
        popover.set_position(Gtk.PositionType.BOTTOM)

        # Create the button
        button = Gtk.MenuButton(
            icon_name="view-more-symbolic",
            valign="center",
            popover=popover)
        button.add_css_class("circular")

        # Add the button
        self.add_suffix(button)

    def update(self, act):
        self.activity = act
        if act.id:
            self.activity_id = act.id
        self.label.set_text(act.name)
        self.time_label.set_text(self.time())
        self.start_label.set_text(self.activity.start.strftime("%c"))

    @property
    def seconds(self):
        return self.activity.seconds

    def time(self):
        return "{:02d}:{:02d}:{:02d}".format(*self.activity.full_time)

    def create_duration_string(self):
        act = self.activity
        if not act.stop:
            return ("<small>{:d}:{:02d} - </small>"
                        .format(*act.start_time, *act.end_time, *act.full_time))
        if act.start.date() == act.stop.date():
            return ("<small>{:d}:{:02d} - {:d}:{:02d} ({:d}:{:02d})</small>"
                        .format(*act.start_time, *act.end_time, *act.full_time))
        else:
            return ("<small>{:(%B %d %y) %H:%M} - {:(%B %d %y) %H:%M} ({:d}:{:02d})</small>"
                        .format(act.start, act.stop, *act.full_time))

