import os
from gettext import gettext as _
from gi.repository import Gtk, Gdk, GLib

import csv
from datetime import datetime, timedelta


@Gtk.Template(resource_path='/net/danigm/timetrack/export_dialog.ui')
class ExportDialog(Gtk.Dialog):
    __gtype_name__ = 'ExportDialog'

    patterns = {
       'TXT': '.txt',
       'CSV': '.csv',
    }

    detailed_switch = Gtk.Template.Child('export-detailed')
    file_type_menu = Gtk.Template.Child('export-filetype')

    activity = Gtk.Template.Child('activity')
    start_date_button = Gtk.Template.Child('export-start')
    end_date_button = Gtk.Template.Child('export-end')

    start_date_calendar = Gtk.Template.Child('export-start-calendar')
    end_date_calendar = Gtk.Template.Child('export-end-calendar')

    file_output = Gtk.Template.Child('file-output')

    def __init__(self, db, main_window, *args, **kwargs):
        self.db = db
        self.main_window = main_window
        super().__init__(*args, title='Export Activity Report',
                         use_header_bar=True, **kwargs)
        self.set_deletable(False)
        self.set_transient_for(main_window)
        self.set_destroy_with_parent(True)
        self.set_modal(True)
        self.file_type_menu.set_active(0)

        default_path = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS)
        default_path = os.path.join(default_path, 'report.txt')
        self.file_output.set_label(default_path)

        # Set the start date to yesterday by default
        yesterday = datetime.today() - timedelta(days=1)
        self.select_datetime(self.start_date_calendar, yesterday)

        # Set the end date to tomorrow by default
        tomorrow = datetime.today() + timedelta(days=1)
        self.select_datetime(self.end_date_calendar, tomorrow)

        self.connect("response", self.response)

    @property
    def file(self):
        return self.file_output.get_label()

    @property
    def file_type(self):
        return self.file_type_menu.get_active_text()

    @property
    def detailed(self):
        return self.detailed_switch.get_state()

    @property
    def start_date_str(self):
        return self.start_date.strftime("%d/%m/%Y")

    @property
    def end_date_str(self):
        return self.end_date.strftime("%d/%m/%Y")

    def response(self, dialog, response_id):
        if response_id == Gtk.ResponseType.OK:
            self.export()
        self.close()

    @Gtk.Template.Callback()
    def choose_output_file(self, *args, **kwargs):
        save_dialog = Gtk.FileChooserNative.new(_("Export To"),
                                                self,
                                                Gtk.FileChooserAction.SAVE,
                                                _("_Ok"),
                                                _("_Cancel"))

        save_dialog.connect("response", self.file_dialog_callback, save_dialog)

        file_types = Gtk.FileFilter()
        file_types.set_name(self.file_type)
        file_types.add_pattern('*' + self.patterns[self.file_type])
        save_dialog.add_filter(file_types)

        save_dialog.show()

    def file_dialog_callback(self, widget, response_id, save_dialog):
        if response_id == Gtk.ResponseType.ACCEPT:
            file = save_dialog.get_file()
            self.file_output.set_label(file.get_path())
        save_dialog.destroy()

    def open(self):
        self.show()

    def select_datetime(self, calendar, date):
        timetuple = date.timetuple()[0:6]
        dt = GLib.DateTime.new_local(*timetuple)
        calendar.select_day(dt)

    def set_default_dates(self, start, end):
        self.select_datetime(self.start_date_calendar, start)
        self.select_datetime(self.end_date_calendar, end)

    @Gtk.Template.Callback()
    def start_date_changed(self, *args, **kwargs):
        selected_date = self.start_date_calendar.get_date()
        date = datetime(selected_date.get_year(),
                        selected_date.get_month(),
                        selected_date.get_day_of_month())

        text = date.strftime("%d/%m/%Y")
        self.start_date_button.set_label(text)
        self.start_date = date

    @Gtk.Template.Callback()
    def end_date_changed(self, *args, **kwargs):
        selected_date = self.end_date_calendar.get_date()
        date = datetime(selected_date.get_year(),
                        selected_date.get_month(),
                        selected_date.get_day_of_month())

        text = date.strftime("%d/%m/%Y")
        self.end_date_button.set_label(text)
        self.end_date = date

    def export(self):
        write_fns = {
                      'TXT': self.TXT_file,
                      'CSV': self.CSV_file,
                    }

        self.write_file(write_fns[self.file_type])

    def seconds_to_time(self, seconds):
        m = seconds // 60
        s = seconds % 60
        h = m // 60
        m = m % 60

        return f"{h:02d}:{m:02d}:{s:02d}"

    def get_activites(self):
        return self.db.report(start=self.start_date, end=self.end_date,
                              activity=self.activity.get_text(),
                              detailed=self.detailed)

    def write_file(self, write_fn):
        start = self.start_date_str
        end = self.end_date_str
        filename = self.file
        extension = self.patterns[self.file_type]

        if not filename.endswith(extension):
            filename += extension

        with open(filename, 'w') as stream:
            write_fn(stream, start, end)

        self.close()

    def CSV_file(self, stream, start, end):
        writer = csv.writer(stream)
        total = 0

        if self.detailed:
            writer.writerow(['Activity', 'Start Date', 'End Date', 'Seconds',
                             'Comment'])

            for act_data in self.get_activites():
                writer.writerow([act_data[1], act_data[2], act_data[3],
                                 act_data[4], act_data[5]])

                total += act_data[4]
        else:
            writer.writerow(['Activity', 'Time'])
            for (activity, seconds) in self.get_activites():
                writer.writerow([activity, seconds])
                total += seconds

        writer.writerow(['Total', total])

    def TXT_file(self, stream, start, end):
        contents = [f"Activity Report: {start} - {end}"]
        contents += [""]
        total = 0

        if self.detailed:
            for act_data in self.get_activites():
                activity = act_data[1]
                start_date = act_data[2]
                end_date = act_data[3]
                seconds = act_data[4]
                comment = act_data[5]

                contents += [""]
                contents += [f"{activity}"]
                contents += [f"\tStart Date: {start_date}"]
                contents += [f"\tEnd Date: {end_date}"]
                contents += [f"\tComment: {comment}"]
                contents += [f"\tTime: {self.seconds_to_time(seconds)}"]

                total += seconds
        else:
            for (activity, seconds) in self.get_activites():
                contents += [f"{activity}: {self.seconds_to_time(seconds)}"]
                total += seconds

        contents += [""]
        contents += ["-" * 80]
        contents += [f"Total: {self.seconds_to_time(total)}"]

        stream.write('\n'.join(contents))
