# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
# Copyright (C) 2012 David Planella <david.planella@ubuntu.com>
# This program is free software: you can redistribute it and/or modify it 
# under the terms of the GNU General Public License version 3, as published 
# by the Free Software Foundation.
# 
# This program is distributed in the hope that it will be useful, but 
# WITHOUT ANY WARRANTY; without even the implied warranties of 
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along 
# with this program.  If not, see <http://www.gnu.org/licenses/>.
### END LICENSE

from .GtkHelpers import clear_text_entry, show_clear_icon
from qreator_lib.i18n import _
from qreator_lib.helpers import get_data_file
import gi
gi.require_version('NM', '1.0')
from gi.repository import Gtk, NM, GLib, GdkPixbuf


def _escape(st):
        """Replace problematic characters with the escaped versions.

        Note that the backslash must be the first character to replace"""
        esc_string = st
        for c in ["\\", ",", ":", ";"]:
            esc_string = esc_string.replace(c, "\\" + c)
        return esc_string
    

class QRCodeWifiGtk(object):
    def __init__(self, qr_code_update_func):
        self.qr_code_update_func = qr_code_update_func
        self.builder = Gtk.Builder()

        self.builder.add_from_file(
            get_data_file('ui', '%s.ui' % ('QrCodeWifi',)))
        self.grid = self.builder.get_object('qr_code_wifi')
        self.builder.connect_signals(self)

        self.comboboxtextSecurity = self.builder.get_object(
            'comboboxtextSecurity')
        self.entryPassword = self.builder.get_object('entryPassword')

        # SSID
        self.entrySSID = self.builder.get_object('entrySSID')
        self.comboboxSSID = self.builder.get_object('comboboxSSID')
        self.SSIDmodel = Gtk.ListStore(str, GdkPixbuf.Pixbuf)
        self.comboboxSSID.set_model(self.SSIDmodel)

        # create the renderers for the strength
        # for some reason, the text renderer already works
        strengthcell = Gtk.CellRendererPixbuf()
        self.comboboxSSID.pack_start(strengthcell, False)
        self.comboboxSSID.add_attribute(strengthcell, 'pixbuf', 1)

        icontheme = Gtk.IconTheme.get_default()
        size = 24
        self.strength_pixbufs = []
        for strength in ["none", "weak", "ok", "good", "excellent"]:
            self.strength_pixbufs.append(icontheme.load_icon(
                "network-wireless-signal-{0}-symbolic".format(strength),
                size, Gtk.IconLookupFlags.USE_BUILTIN))

        # Initialize combo boxes (Glade seems not to do it for us)
        self.comboboxtextSecurity.set_active(0)

        # TRANSLATORS: 'expand' refers to expanding the drop-down menu
        # that shows autodetected wireless network identifiers
        self.entrySSID.set_placeholder_text(
            _('[Network identifier - expand for autodetection]'))
        self.entryPassword.set_placeholder_text(_('[Network password]'))

    def update_ssids(self):
        # check if there are already ssids in the combobox
        ssidlistmodel = self.comboboxSSID.get_model()
        ssidelements = []
        item = ssidlistmodel.get_iter_first()
        while not item is None:
            ssidelements.append(ssidlistmodel.get_value(item, 0))
            item = ssidlistmodel.iter_next(item)
        
        # get the new ssids from the network manager
        # and add them to combobox
        ssids = get_ssids()
        for ssid in ssids:
            if not ssid[1] in ssidelements:
                p = self.strength_pixbufs[min(99, ssid[0]) // 25]
                self.SSIDmodel.append([ssid[1], p])
                self.comboboxSSID.set_model(self.SSIDmodel)

        return True  # -> repeat the timeout calls

    def update_wifi_qr_code(self, security=None, ssid=None, password=None):
        if not security:
            security = self.comboboxtextSecurity.get_active_text()
        if not ssid:
            ssid = self.entrySSID.get_text()
        if not password:
            password = self.entryPassword.get_text()

        if not security or ssid == '' or password == '':
            return

        wifi_qr_code = 'WIFI:T:{0};S:{1};P:{2};;'.format(_escape(security), _escape(ssid),
                                                         _escape(password))
        self.qr_code_update_func(wifi_qr_code)

    def on_comboboxtextSecurity_changed(self, widget, data=None):
        self.update_wifi_qr_code(security=widget.get_active_text())

    def on_entrySSID_icon_press(self, widget, icon, mouse_button):
        clear_text_entry(widget, icon)

    def on_comboboxSSID_changed(self, widget, data=None):
        show_clear_icon(self.entrySSID)
        self.update_wifi_qr_code(ssid=widget.get_child().get_text())

    def on_entryPassword_icon_press(self, widget, icon, mouse_button):
        clear_text_entry(widget, icon)

    def on_entryPassword_changed(self, widget, data=None):
        show_clear_icon(widget)
        self.update_wifi_qr_code(password=widget.get_text())

    def on_checkbutton1_clicked(self, widget):
        if widget.get_active():
            self.entryPassword.set_visibility(True)
        else:
            self.entryPassword.set_visibility(False)

    def on_activated(self):
        pass

    def on_prepared(self):
        # check for new ssids every 5 seconds
        GLib.timeout_add_seconds(5, self.update_ssids)


def get_ssids():
    """Returns a list of ssids sorted by the signal strength."""
    nmc = NM.Client.new()
    devs = nmc.get_devices()

    ssids = []
    for dev in devs:
        if dev.get_device_type() == NM.DeviceType.WIFI:
            for ap in dev.get_access_points():
                ssid_gbytes = ap.get_ssid()

                # Unknown SSIDs are None
                if ssid_gbytes:
                    ssid = NM.utils_ssid_to_utf8(ssid_gbytes.get_data())
                    ssids.append((ap.get_strength(), ssid))
    ssids.sort()
    ssids.reverse()   # strongest has the highest number -> should be first
    return ssids
