# element_info.py
#
# Copyright 2024 Lo
#
# 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 <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

import gi, json
import re as regex
from gi.repository import Adw, Gtk, Gio, GObject
from .utils import get_category_color


@Gtk.Template(resource_path="/page/codeberg/lo_vely/Nucleus/ui/property-card.ui")
class NucleusPropertyCard(Gtk.Box):
    __gtype_name__ = "NucleusPropertyCard"

    title = GObject.Property(type=str)
    value = GObject.Property(type=str)
    icon_name = GObject.Property(type=str)
    has_icon = GObject.Property(type=bool, default=True)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)


@Gtk.Template(resource_path="/page/codeberg/lo_vely/Nucleus/ui/property-row.ui")
class NucleusPropertyRow(Adw.ActionRow):
    __gtype_name__ = "NucleusPropertyRow"

    def __init__(self, **kwargs):
        super().__init__(**kwargs)


@Gtk.Template(resource_path="/page/codeberg/lo_vely/Nucleus/ui/element-info.ui")
class NucleusElementInfo(Gtk.Box):
    __gtype_name__ = "NucleusElementInfo"

    element_card = Gtk.Template.Child()

    atomic_number = Gtk.Template.Child()
    element_symbol = Gtk.Template.Child()
    element_name = Gtk.Template.Child()
    element_property = Gtk.Template.Child()

    theoretical_indicator = Gtk.Template.Child()

    group_card = Gtk.Template.Child()
    period_card = Gtk.Template.Child()
    block_card = Gtk.Template.Child()

    protons_card = Gtk.Template.Child()
    electrons_card = Gtk.Template.Child()
    neutrons_card = Gtk.Template.Child()

    general_props = Gtk.Template.Child()
    physical_props = Gtk.Template.Child()
    atomic_props = Gtk.Template.Child()
    other_props = Gtk.Template.Child()

    electron_shell_row = Gtk.Template.Child()
    cpk_color_row = Gtk.Template.Child()
    cpk_color_preview = Gtk.Template.Child()

    data = None

    def __init__(self, data, **kwargs):
        super().__init__(**kwargs)

        self.data = data

        self.group_card.props.value = self.data['group']
        self.period_card.props.value = self.data['period']
        self.block_card.props.value = self.data['block']

        self.protons_card.props.value = self.data['number']
        self.electrons_card.props.value = self.data['number']
        self.neutrons_card.props.value = round(self.data['atomic_mass'] - self.data['number'])

        self.atomic_number.props.label = str(data['number'])
        self.element_symbol.props.label = data['symbol']
        self.element_name.props.label = data['name']
        self.element_property.props.label = data['category'].capitalize()
        get_category_color(self.element_card, data['category'], activatable=False)

        if "theoretical" in data:
            self.theoretical_indicator.props.visible = True

        if data['cpk-hex'] is not None:
            self.cpk_color_row.props.subtitle = f"#{data['cpk-hex']}"
            self.cpk_color_row.props.sensitive = True

            css_provider = Gtk.CssProvider()
            css_provider.load_from_string(f".cpk-color {{background: #{data['cpk-hex']};}}")
            self.cpk_color_preview.get_style_context().add_provider(
                css_provider,
                Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
            )
            self.cpk_color_preview.add_css_class('cpk-color')
            self.cpk_color_preview.props.visible = True

        general_properties = [
            {'property_name':'summary', 'title':_("Summary")},
            {'property_name':'appearance', 'title':_("Appearance")},
            {'property_name':'atomic_mass', 'title':_("Atomic Mass"), 'unit':'u'},
        ]

        # The Kelvin sign used here is Unicode K (U+212A)
        physical_properties = [
            {'property_name':'phase', 'title':_("Phase"), 'icon':True},
            {'property_name':'density', 'title':_("Density"), 'unit':'g/cm<sup>3</sup>'},
            {'property_name':'melt', 'title':_("Melting Point"), 'unit':'K'},
            {'property_name':'boil', 'title':_("Boilling Point"), 'unit':'K'},
            {'property_name':'molar_heat', 'title':_("Molar Heat Capacity"), 'unit':'J/(mol·K)'}
        ]
        if "half-life" in self.data:
            unit = _("years") # Default unit
            if "half-life:unit" in self.data:
                unit = self.data["half-life:unit"]
            physical_properties.append({'property_name':'half-life', 'title': _("Half-life") + f" (<sup>{self.data['half-life:isotope']}</sup>{self.data['symbol']})", 'unit': unit})

        atomic_properties = [
            {'property_name':'electron_configuration_semantic', 'title':_("Electron Configuration")},
            {'property_name':'electron_affinity', 'title':_("Electron Affinity"), 'unit':'kJ/mol'},
            {'property_name':'electronegativity_pauling', 'title':_("Pauling Electronegativity")},
        ]

        other_properties = [
            {'property_name':'discovered_by', 'title':_("Discovered by")},
            {'property_name':'named_by', 'title':_("Named by")},
        ]

        for property in general_properties:
            self.add_property_row(property, self.general_props)

        for property in physical_properties:
            self.add_property_row(property, self.physical_props)

        for property in atomic_properties:
            self.add_property_row(property, self.atomic_props)

        for property in other_properties:
            self.add_property_row(property, self.other_props)


    def add_property_row(self, property, group):
        row = NucleusPropertyRow(
            title=property['title'],
            subtitle=f"{self.data[property['property_name']]}",
        )

        if (self.data[property['property_name']] == "" or self.data[property['property_name']] is None):
            row.props.subtitle = "-"
            row.props.sensitive = False
            group.add(row)
            return

        if 'unit' in property:
            if self.data['phase'] == 'Gas' and property['property_name'] == 'density':
                row.props.subtitle += " g/L"
            else:
                row.props.subtitle += f" {property['unit']}"

            if property['unit'] == 'K':
                row.props.subtitle = self.convert_temp(self.data[property['property_name']])

        if 'icon' in property:
            icon = Gtk.Image()

            if self.data['phase'] == _("Gas"):
                icon.props.icon_name = "gas-symbolic"
            elif self.data['phase'] == _("Solid"):
                icon.props.icon_name = "solid-symbolic"
            elif self.data['phase'] == _("Liquid"):
                icon.props.icon_name = "liquid-symbolic"

            row.add_suffix(icon)

        group.add(row)


    def convert_temp(self, kelvin) -> str:
        fahrenheit = ((kelvin - 273.15) * 1.8) + 32
        celcius = kelvin - 273.15

        return f"{kelvin} K = {fahrenheit:.2f} ℉ = {celcius:.2f} ℃"


