#!/usr/bin/env python3
"""
Syncthing-GTK - DeviceEditorDialog

Universal dialog handler for all Syncthing settings and editing
"""


import logging

from gi.repository import Gtk

from syncthing_gtk.editordialog import EditorDialog, strip_v
from syncthing_gtk.tools import _  # gettext function
from syncthing_gtk.tools import check_device_id


log = logging.getLogger("DeviceEditor")

COLOR_NEW = "#A0A0A0"
VALUES = ["vdeviceID", "vname", "vaddresses", "vcompression",
          "vfolders", "vintroducer"
          ]


class DeviceEditorDialog(EditorDialog):
    MESSAGES = {
        # Displayed when device id is invalid
        "vdeviceID": _("The entered device ID does not look valid. It "
                       "should be a 52 character string consisting of letters and "
                       "numbers, with spaces and dashes being optional."),
    }

    def __init__(self, app, is_new, id=None):
        EditorDialog.__init__(
            self, app, "device-edit.ui",
            "New Device" if is_new else "Edit Device")
        self.id = id
        self.is_new = is_new

    # @Overrides
    def get_value(self, key):
        if key == "addresses":
            return ",".join([strip_v(x) for x in self.values[key]])
        elif key == "deviceID":
            return EditorDialog.get_value(self, key).strip(" \r\n\t")
        elif key == "compression":
            val = EditorDialog.get_value(self, key)
            # For syncthing <= 0.10.25
            if val in (True, "true"):
                return "always"
            elif val in (False, "false"):
                return "never"
            else:
                return val
        else:
            return EditorDialog.get_value(self, key)

    # @Overrides
    def set_value(self, key, value):
        if key == "addresses":
            self.values[key] = [strip_v(x) for x in value.split(",")]
        else:
            return EditorDialog.set_value(self, key, value)

    # @Overrides
    def on_data_loaded(self):
        try:
            if self.is_new:
                self.values = {strip_v(x): "" for x in VALUES}
                self.set_value("addresses", "dynamic")
                self.set_value("compression", "metadata")
                self.checks = {
                    "vdeviceID": check_device_id,
                }
                if self.id is not None:
                    # Pre-fill device id, if provided
                    self.set_value("deviceID", self.id)
            else:
                self.values = [x for x in self.config["devices"]
                               if x["deviceID"] == self.id][0]
        except KeyError as e:
            # ID not found in configuration. This is practically impossible,
            # so it's handled only by self-closing dialog.
            log.exception(e)
            self.close()
            return
        return self.display_values(VALUES)

    # @Overrides
    def display_value(self, key, w):
        if key == "vfolders":
            # Even more special case
            rids = []
            # Get list of folders that share this device
            for r in self.config["folders"]:
                for n in r["devices"]:
                    if n["deviceID"] == self.id and r["id"] not in rids:
                        rids.append(r["id"])
            # Create CheckButtons
            for folder in reversed(sorted(self.app.folders.values(), key=lambda x: x["id"])):
                b = Gtk.CheckButton(folder["path"], False)
                b.set_tooltip_text(folder["id"])
                self["vfolders"].pack_start(b, False, False, 0)
                b.set_active(folder["id"] in rids)
            self["vfolders"].show_all()
        else:
            EditorDialog.display_value(self, key, w)

    # @Overrides
    def update_special_widgets(self, *a):
        self["vdeviceID"].set_sensitive(self.is_new)

    # @Overrides
    def on_save_requested(self):
        self.store_values(VALUES)
        if self.is_new:
            # Add new dict to configuration (edited dict is already there)
            self.config["devices"].append(self.values)
        # Post configuration back to daemon
        self.post_config()

    # @Overrides
    def store_value(self, key, w):
        if key == "vaddresses":
            addresses = [
                x.strip() if "://" in x or x.strip() == "dynamic" else "tcp://%s" % (x.strip(),)
                for x in w.get_text().split(",")]
            self.set_value("addresses", ",".join(addresses))
        elif key == "vfolders":
            # Generate dict of { folder_id : bool } where bool is True if
            # folder should be shared with this device
            folders = {}
            for b in self["vfolders"].get_children():
                folders[b.get_tooltip_text()] = b.get_active()
            # Go over all Folders/<folder>/Devices/<device> keys in config
            # and set them as needed
            nid = self.get_value("deviceID")
            for r in self.config["folders"]:
                rid = r["id"]
                found = False
                for n in r["devices"]:
                    if n["deviceID"] == nid:
                        if rid not in folders or not folders[rid]:
                            # Remove this /<device> key (unshare folder with device)
                            r["devices"].remove(n)
                            break
                        found = True
                if (not found) and (rid in folders) and folders[rid]:
                    # Add new /<device> key (share folder with device)
                    r["devices"].append({
                        "addresses": None,
                        "deviceID": nid,
                        "name": "",
                        "certName": "",
                        "compression": "metadata"
                    })
        else:
            EditorDialog.store_value(self, key, w)

    # @Overrides
    def on_saved(self):
        self.close()
