#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Copyright (c) 2014-2024 Arturo Martín Romero <amartinromero@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY 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/>.

__author__ = [
    "Arturo Martín Romero <amartinromero@gmail.com>",
    "Nacho Sancho Morte <sannacho@gmail.com>",
]
__license__ = "GPLv3"
__copyright__ = "(C) 2014-2024 Vitalinux team"

import os
import sys
import subprocess
import gettext
import logging

_ = gettext.gettext
gettext.bindtextdomain(
    "vx-pantallas-conmutador", "/usr/share/locale"
)
gettext.textdomain("vx-pantallas-conmutador")

from gi import require_version

require_version("Gtk", "3.0")

from gi.repository import (
    Gio,
    GLib,
    GObject,
    Gtk as gtk,
)


def obtener_version_paquete_apt(nombre_paquete):
    try:
        resultado = subprocess.run(
            ["dpkg", "-s", nombre_paquete],
            stdout=subprocess.PIPE,
            check=True,
            universal_newlines=True,
        )
        lineas = resultado.stdout.split("\n")
        for linea in lineas:
            if linea.startswith("Version:"):
                _version = linea.split(" ")[1]
                return _version
    except subprocess.CalledProcessError:
        return None


__paquete__ = "vx-dga-l-pantallas-conmutador"
__version__ = obtener_version_paquete_apt(__paquete__)


class PantallasConmutadorWindow(gtk.Window):
    # Definimos las constantes:
    APP_ID = "vx-dga-l-pantallas-conmutador"
    APP_NAME = _("Screen Resolution Switch")
    APP_LICENCE = """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/"""
    
    APP_VERSION = __version__
    APP_ICON = "vx-pantallas-conmutador"
    APP_ICON_ORANGE = "vx-pantallas-conmutador-orange"
    
    CMD_DCONF_SCHEMA = "dconf-editor"
    CMD_LXRAND_SET = "vx-lxrand-set"
    VX_LXRAND_OPERATION_TIPO_DEFAULT = "auto"
    CMD_DISPLAY_SETTINGS = "xfce4-display-settings"
    CMD_CONFIGURE_OPTIONS = "vx-pantallas-conmutador-indicator-update"
    CMD_NATIVE_RESOLUTION = "vx-lxrand-set -m auto -x native"
    SCHEMA_BASE = "org.vitalinux.pantallas-conmutador"
    URL_SOPORTE = "https://soporte.vitalinux.educa.aragon.es"
    URL_GITLAB = "https://gitlab.vitalinux.educa.aragon.es/vitalinux-devops/vx-dga-l-pantallas-conmutador"

    def gsettings_set(self, schema, rama, param, value):
        if rama is not None:
            _ruta = schema + "." + rama
        else:
            _ruta = schema
        _settings = Gio.Settings.new(_ruta)
        _settings.set_boolean(param, bool(int(value)))

    def gsettings_get(self, schema, rama, param):
        if rama is not None:
            _ruta = schema + "." + rama
        else:
            _ruta = schema
        _settings = Gio.Settings.new(_ruta)
        return _settings.get_value(param)

    def __init__(self):
        gtk.Window.__init__(self, title=self.APP_NAME)
        self.set_icon_name(self.APP_ICON)
        self.set_resizable(False)
        self.set_border_width(10)
        self.set_position(gtk.WindowPosition.CENTER)
        # Fijamos la anchura de la ventana (400) y una altura automática (-1):
        self.set_default_size(400, -1)

        # Mostramos la información del dimensiones de la pantalla por defecto:
        self.run_obtener_size()
        
        # Conectamos la señal "changed" del objeto GSettings para actualizar
        self.settings = Gio.Settings.new(self.SCHEMA_BASE)
        self.settings.connect("changed", self.on_settings_changed)

        self.construct_ui()

    def construct_ui(self):
        # Limpiamos los hijos si existen (para rebuild)
        for child in self.get_children():
            self.remove(child)

        vbox = gtk.Box(orientation=gtk.Orientation.VERTICAL, spacing=6)
        self.add(vbox)

        # --- Zona de Resoluciones (Radio Buttons) ---
        label_res = gtk.Label()
        label_res.set_markup(f"<b>{_('Resolutions')}</b>")
        label_res.set_xalign(0)
        vbox.pack_start(label_res, False, False, 0)
        
        self.radio_group = None
        
        # Generar lista de elementos
        el0 = _("Default")
        el1 = _("Resolution")
        
        lista_elementos = [f"{el0} {self.resolucion}"]
        
        # 16x9
        lista_elementos.append(f"{el1} 16x9:vx-monitor-16_9")
        _lista_16_9 = self.gsettings_get(self.SCHEMA_BASE, None, "r16-9")
        for el in _lista_16_9:
            partes = el.split(":")
            _modo = partes[0].split(" ")
            _modo[0] = _(_modo[0])
            lista_elementos.append(" ".join(_modo) + " '" + partes[2] + "'")
            
        # 4x3
        lista_elementos.append(f"{el1} 4x3:vx-monitor-4_3")
        _lista_4_3 = self.gsettings_get(self.SCHEMA_BASE, None, "r4-3")
        for el in _lista_4_3:
            partes = el.split(":")
            _modo = partes[0].split(" ")
            _modo[0] = _(_modo[0])
            lista_elementos.append(" ".join(_modo) + " '" + partes[2] + "'")

        size = self.resolucion
        self.radio_buttons = []

        for el in lista_elementos:
            partes = el.split(":")
            if len(partes) > 1:
                # Es una cabecera/sección
                etiqueta = partes[0]
                size = partes[0].split(" ")[1]
                imagen = partes[1]
                
                hbox_header = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
                img_widget = gtk.Image.new_from_icon_name(imagen, gtk.IconSize.MENU)
                lbl_widget = gtk.Label()
                lbl_widget.set_markup(f"<b>{etiqueta}</b>")
                hbox_header.pack_start(img_widget, False, False, 0)
                hbox_header.pack_start(lbl_widget, False, False, 0)
                vbox.pack_start(hbox_header, False, False, 5)
                
            else:
                # Es una opción de radio
                etiqueta = partes[0]
                full_label = f"{etiqueta} [{size}]"
                
                if self.radio_group is None:
                    rb = gtk.RadioButton.new_with_label_from_widget(None, full_label)
                    self.radio_group = rb
                else:
                    rb = gtk.RadioButton.new_with_label_from_widget(self.radio_group, full_label)
                
                # Guardamos el dato de resolución en el widget para usarlo luego
                # El formato es "Nombre 'RESOLUCION'" -> queremos la resolución
                try:
                    res_val = etiqueta.split("'")[1]
                except IndexError:
                    res_val = self.resolucion # Fallback

                rb.resolution = res_val
                rb.connect("toggled", self.on_radio_toggled)
                vbox.pack_start(rb, False, False, 0)
                self.radio_buttons.append(rb)

        vbox.pack_start(gtk.Separator(orientation=gtk.Orientation.HORIZONTAL), False, False, 5)

        # --- Botones de Acción ---
        
        # Native Resolution
        btn_native = gtk.Button(label=_("Native Resolution"))
        btn_native.set_image(gtk.Image.new_from_icon_name("vx-pantallas-resolucion-nativa", gtk.IconSize.BUTTON))
        btn_native.set_always_show_image(True)
        btn_native.connect("clicked", self.run_native_resolution)
        vbox.pack_start(btn_native, False, False, 0)

        # Configure Screens
        btn_config = gtk.Button(label=_("Configure Screens"))
        btn_config.set_image(gtk.Image.new_from_icon_name("vx-pantallas-configuracion", gtk.IconSize.BUTTON))
        btn_config.set_always_show_image(True)
        btn_config.connect("clicked", self.run_display_settings)
        vbox.pack_start(btn_config, False, False, 0)

        # Configure Options
        btn_opts = gtk.Button(label=_("Configure options"))
        btn_opts.set_image(gtk.Image.new_from_icon_name("vx-configuracion-pantallas-conmutador", gtk.IconSize.BUTTON))
        btn_opts.set_always_show_image(True)
        btn_opts.connect("clicked", self.run_dconf)
        vbox.pack_start(btn_opts, False, False, 0)

        # Support
        btn_support = gtk.Button(label=_("Support and Incidents"))
        btn_support.set_image(gtk.Image.new_from_icon_name("migasfree", gtk.IconSize.BUTTON))
        btn_support.set_always_show_image(True)
        btn_support.connect("clicked", self.run_soporte)
        vbox.pack_start(btn_support, False, False, 0)

        vbox.pack_start(gtk.Separator(orientation=gtk.Orientation.HORIZONTAL), False, False, 5)

        # --- Opciones Finales ---
        
        # Disable Checkbox
        self.check_disable_widget = gtk.CheckButton(label=_("Disable"))
        self.check_disable_widget.connect("toggled", self.checkbox_toggled)
        vbox.pack_start(self.check_disable_widget, False, False, 0)

        # About & Exit
        hbox_bottom = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
        
        btn_about = gtk.Button(label=_("About"))
        btn_about.set_image(gtk.Image.new_from_icon_name("vx-info-about-pantallas-conmutador", gtk.IconSize.BUTTON))
        btn_about.connect("clicked", self.on_about)
        hbox_bottom.pack_start(btn_about, True, True, 0)
        
        btn_close = gtk.Button(label=_("Close"))
        btn_close.set_image(gtk.Image.new_from_icon_name("vx-salir", gtk.IconSize.BUTTON))
        btn_close.connect("clicked", self.on_close)
        hbox_bottom.pack_start(btn_close, True, True, 0)
        
        vbox.pack_start(hbox_bottom, False, False, 5)
        
        # Estado inicial check disable
        self.check_disable_init()
        
        self.show_all()

    def run_obtener_size(self):
        comando = ["obtener-resolucion-pantalla"]
        _resultado = self.ejecutar_comando_output(comando)
        if _resultado:
            self.resolucion = _resultado.replace(":", "x")
        else:
            self.resolucion = "Unknown"

    def ejecutar_comando_output(self, comando):
        try:
            resultado = subprocess.check_output(
                comando, shell=True, universal_newlines=True
            )
            return resultado.strip()
        except subprocess.CalledProcessError as e:
            print(f"Error: {e}")
            return None    

    def ejecutar_comando_run(self, comando):
        subprocess.run(comando, shell=True)

    def run_pantallas_conmutador(self):
        comando = [
            self.CMD_LXRAND_SET,
            "-m",
            self.VX_LXRAND_OPERATION_TIPO_DEFAULT,
            "-x",
            self.resolucion,
        ]
        print(f"Executing: {comando}")
        subprocess.run(comando)

    def on_radio_toggled(self, widget):
        if widget.get_active():
            self.resolucion = widget.resolution
            print(f"Selected resolution: {self.resolucion}")
            self.run_pantallas_conmutador()

    def run_native_resolution(self, widget):
        self.ejecutar_comando_run(self.CMD_NATIVE_RESOLUTION)

    def run_display_settings(self, widget):
        self.ejecutar_comando_run(self.CMD_DISPLAY_SETTINGS)

    def run_dconf(self, widget):
        comando = [self.CMD_CONFIGURE_OPTIONS]
        subprocess.run(comando, shell=True)

    def run_soporte(self, widget):
        subprocess.call(["xdg-open", self.URL_SOPORTE])

    def check_disable_init(self):
        _estado = self.gsettings_get(self.SCHEMA_BASE, None, "disable")
        if _estado:
            self.check_disable_widget.set_active(True)
            self.set_sensitive_radios(False)
        else:
            self.check_disable_widget.set_active(False)
            self.set_sensitive_radios(True)

    def checkbox_toggled(self, widget):
        if widget.get_active():
            self.gsettings_set(self.SCHEMA_BASE, None, "disable", 1)
            self.set_sensitive_radios(False)
        else:
            self.gsettings_set(self.SCHEMA_BASE, None, "disable", 0)
            self.set_sensitive_radios(True)

    def set_sensitive_radios(self, sensitive):
        for rb in self.radio_buttons:
            rb.set_sensitive(sensitive)

    def on_settings_changed(self, settings, key):
        print(f"GSettings {key} changed. Refreshing UI...")
        # Si cambia algo que afecte al menú (listas), reconstruimos.
        # Si cambia solo disable, ya se maneja con el toggle, pero por seguridad podemos refrescar todo
        # Nota: Al reconstruir se pierde el foco, pero asegura consistencia.
        self.construct_ui()

    def on_about(self, widget):
        dialog = gtk.AboutDialog(transient_for=self, modal=True)
        dialog.set_program_name(self.APP_NAME)
        _written_by = _("Written by")
        _autores = "\n".join(__author__)
        _copyright = f"{_written_by}:\n{_autores}\n{__copyright__}"
        dialog.set_copyright(_copyright)
        dialog.set_license(self.APP_LICENCE)
        dialog.set_version(self.APP_VERSION)
        dialog.set_website(self.URL_GITLAB)
        dialog.set_website_label("Gitlab Vitalinux")
        try:
            dialog.set_icon_name(self.APP_ICON_ORANGE)
            dialog.set_logo_icon_name(self.APP_ICON_ORANGE)
        except:
            pass
        dialog.run()
        dialog.destroy()

    def on_close(self, widget):
        self.destroy()


if __name__ == "__main__":
    win = PantallasConmutadorWindow()
    win.connect("destroy", gtk.main_quit)
    win.show()
    gtk.main()
