
from kivy.properties import ObjectProperty, StringProperty, ListProperty
from datetime import datetime, timedelta
from kivy.core.text import LabelBase
from kivy.metrics import dp
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivymd.app import MDApp
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.datatables import MDDataTable
import random
import threading
import csv
from kivymd.uix.textfield import MDTextField
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.label import MDLabel
from kivy.uix.label import Label

from kivy.utils import platform
from kivy.clock import Clock
from kivy.uix.widget import Widget

from kivy.graphics import Color, Rectangle
from kivy_garden.graph import Graph, LinePlot

import modbus_tk
import modbus_tk.defines as cst
import socket
from modbus_client import ModbusClient
import re
from threading import Thread
from functools import partial
from collections import defaultdict

from random import randint  
from kivymd.theming import ThemeManager

LabelBase.register(name="MPoppins", fn_regular="fonts/Chinese/msyh.ttf")
LabelBase.register(name="BPoppins", fn_regular="fonts/Chinese/msyh.ttf")
LabelBase.register(name="RRubik",   fn_regular="fonts/Chinese/msyh.ttf")
LabelBase.register(name="RCro",     fn_regular="fonts/Chinese/msyh.ttf")
LabelBase.register(name="RPac",     fn_regular="fonts/Chinese/msyh.ttf")


class MainScreen(Screen):
    pass
class HomeScreen(Screen):
    home = ObjectProperty(None)
class LoginScreen(Screen):
    login = ObjectProperty(None)
class ProfileScreen(Screen):
    profile = ObjectProperty(None)
class ProfileEditScreen(Screen):
    profile_edit = ObjectProperty(None)
class HistoryScreen(Screen):
    history = ObjectProperty(None)

class ModifyCurrentParamScreen(Screen):
    modify_current_param = ObjectProperty(None)
class ModifyVoltageParamScreen(Screen):
    modify_voltage_param = ObjectProperty(None)
class ModifyLeakageParamScreen(Screen):
    modify_leakage_param = ObjectProperty(None)
class ModifySystemParamScreen(Screen):
    modify_system_param = ObjectProperty(None)
class ModifyProtectionParamScreen(Screen):
    modify_protection_param = ObjectProperty(None)
class RealTimeCurveScreen(Screen):
    real_time_curve = ObjectProperty(None)
class ControlCommandScreen(Screen):
    control_command = ObjectProperty(None)
class AboutScreen(Screen):
    about = ObjectProperty(None)


# Window.size = (dp(360), dp(680))

class app(MDApp):
    wifi_status_text = StringProperty("")
    def __init__(self):
        super().__init__()

        self.user_name = None
        self.dialog = None
        self.dialog2 = None

        self.profile_edit_screen = None

        self.edit_user_pass = None
        self.edit_user_name = None
        self.edit_wifi_ssid = None
        self.edit_modbus_ip = None
        self.edit_modbus_port = None
        self.edit_nfc_id = None
        self.edit_reserve = None

     
        self.profile_user_pass = None
        self.profile_user_name = None
        self.profile_wifi_ssid = None
        self.profile_modbus_ip = None
        self.profile_modbus_port = None  
        self.profile_nfc_id = None
        self.profile_reserve = None


        self.user_pass = None
        self.d1 = None
        self.edit_semester = None
        self.otp_button = None
        self.new_pass = None
        self.new_pass1 = None
        self.mobile_no = None
        self.password = None
        self.username = None

        self.modbus_master = ModbusClient()  # Modbus连接对象
        self.modbus_ip = None      # Modbus服务器IP
        self.modbus_port = None    # Modbus服务器端口


        self.theme_cls.font_styles["H1"]    =       ["BPoppins", 96, False, -1.5]
        self.theme_cls.font_styles["H2"]    =       ["BPoppins", 60, False, -0.5]
        self.theme_cls.font_styles["H3"]    =       ["BPoppins", 48, False, 0]
        self.theme_cls.font_styles["H4"]    =       ["BPoppins", 34, False, 0.25]
        self.theme_cls.font_styles["H5"]    =       ["BPoppins", 25, False, 0.15]
        self.theme_cls.font_styles["H6"]    =       ["BPoppins", 16, False, 0.15]
        self.theme_cls.font_styles["Subtitle1"] =   ["BPoppins", 16, False, 0.15]
        self.theme_cls.font_styles["Subtitle2"] =   ["BPoppins", 14, False, 0.1]
        self.theme_cls.font_styles["Body1"] =       ["BPoppins", 16, False, 0.5]
        self.theme_cls.font_styles["Body2"] =       ["BPoppins", 14, False, 0.25]
        self.theme_cls.font_styles["Button"] =      ["BPoppins", 14, True, 1.25]
        self.theme_cls.font_styles["Caption"] =     ["BPoppins", 13, False, 0.15]
        self.theme_cls.font_styles["Overline"] =    ["BPoppins", 10, True, 1.5]

    def on_text_field_focus(self, instance, value):
        if value:
            # 当MDTextField获得焦点时
            # 获取ScrollView和MDList的引用
            scroll_view = self.root.get_screen('modify_current_param').ids.real_time_scroll_view
            md_list = self.root.get_screen('modify_current_param').ids.real_time_md_list

            # 计算MDTextField在MDList中的相对位置
            # instance.y 是MDTextField在父控件（BoxLayout）中的y坐标
            # instance.parent.y 是BoxLayout在MDList中的y坐标
            # 所以MDTextField在MDList中的y坐标是 instance.y + instance.parent.y
            text_field_y_in_mdlist = instance.y + instance.parent.y

            # 计算需要滚动的目标位置
            # 目标是让MDTextField的底部与ScrollView的底部对齐，或者至少在可见区域内
            # scroll_view.height 是ScrollView的可见高度
            # md_list.height 是MDList的总高度
            # scroll_view.scroll_y 的范围是0到1，0表示底部，1表示顶部

            # 计算MDTextField相对于MDList顶部的距离
            relative_y = md_list.height - text_field_y_in_mdlist - instance.height

            # 将相对距离转换为scroll_y的值
            # 确保不会滚动到超出范围
            if md_list.height > scroll_view.height:
                target_scroll_y = relative_y / (md_list.height - scroll_view.height)
                # 限制target_scroll_y在0到1之间
                target_scroll_y = max(0, min(1, target_scroll_y))
                scroll_view.scroll_y = target_scroll_y

    def build(self):
        Builder.load_file('kv/app.kv')
        screen_manager = ScreenManager()
        screen_manager.add_widget(MainScreen(name="main"))
        screen_manager.add_widget(HomeScreen(name="home"))
        screen_manager.add_widget(LoginScreen(name="login"))
        screen_manager.add_widget(HistoryScreen(name="history"))
        screen_manager.add_widget(ProfileScreen(name="profile"))
        screen_manager.add_widget(ProfileEditScreen(name="profile_edit"))
        
        screen_manager.add_widget(ModifyCurrentParamScreen(name="modify_current_param"))
        screen_manager.add_widget(ModifyVoltageParamScreen(name="modify_voltage_param"))
        screen_manager.add_widget(ModifyLeakageParamScreen(name="modify_leakage_param"))
        screen_manager.add_widget(ModifySystemParamScreen(name="modify_system_param"))
        screen_manager.add_widget(ModifyProtectionParamScreen(name="modify_protection_param"))
        screen_manager.add_widget(RealTimeCurveScreen(name="real_time_curve"))
        screen_manager.add_widget(ControlCommandScreen(name="control_command"))
        screen_manager.add_widget(AboutScreen(name="about"))

        # 添加其他屏幕


        return screen_manager

#############################################ALL INPUT TEXT############################################################
    def on_start(self):

        login_screen = self.root.get_screen("login")

        home_screen = self.root.get_screen("home")
        self.user = home_screen.ids.user

        profile_screen = self.root.get_screen("profile")
        self.profile_user_name = profile_screen.ids.profile_user_name
        self.profile_user_pass = profile_screen.ids.profile_user_pass
        self.profile_wifi_ssid = profile_screen.ids.profile_wifi_ssid
        self.profile_modbus_ip = profile_screen.ids.profile_modbus_ip
        self.profile_modbus_port = profile_screen.ids.profile_modbus_port
        self.profile_nfc_id = profile_screen.ids.profile_nfc_id
        self.profile_reserve = profile_screen.ids.profile_reserve

        self.profile_edit_screen = self.root.get_screen("profile_edit")

        self.edit_user_name = self.profile_edit_screen.ids.edit_user_name
        self.edit_user_pass = self.profile_edit_screen.ids.edit_user_pass
        self.edit_wifi_ssid = self.profile_edit_screen.ids.edit_wifi_ssid
        self.edit_modbus_ip = self.profile_edit_screen.ids.edit_modbus_ip
        self.edit_modbus_port = self.profile_edit_screen.ids.edit_modbus_port
        self.edit_nfc_id = self.profile_edit_screen.ids.edit_nfc_id
        self.edit_reserve = self.profile_edit_screen.ids.edit_reserve


        self.root.bind(current=self.on_screen_changed)
        self.register_update_event = None
        self.wifi_update_event = None

    def on_screen_changed(self, instance, value):
        """屏幕切换时启动/停止刷新"""
        if value == "real_time_curve":
            # 进入目标屏幕时启动定时刷新
            if not self.register_update_event:
                self.register_update_event = Clock.schedule_interval(self.update_register_display, 1)
        else:
            # 离开时停止刷新
            if self.register_update_event:
                self.register_update_event.cancel()
                self.register_update_event = None
        
        if value == "login":
            if not self.wifi_update_event:
                self.wifi_update_event = Clock.schedule_interval(self.update_wifi_status, 1)
        else:
            if self.wifi_update_event:
                self.wifi_update_event.cancel()
                self.wifi_update_event = None

#############################################@Frequently used functions##################################################

    @staticmethod
    def change_cursor(is_enter):
        """改变鼠标指针样式"""
        # 如果is_enter为True（鼠标进入目标区域），将鼠标指针改为手型
        if is_enter:
            Window.set_system_cursor('hand')
        # 否则（鼠标离开目标区域），将鼠标指针改回默认箭头样式
        else:
            Window.set_system_cursor('arrow')

    @staticmethod
    def toggle_password_visibility(password_field, icon_button):
        """切换密码输入框的可见性状态"""
        # 检查密码输入框当前是否处于密码隐藏状态
        if password_field.password:
            # 如果是隐藏状态，切换为可见状态
            password_field.password = False
            # 更新图标为"eye"（眼睛图标，表示当前可见）
            icon_button.icon = "eye"
        else:
            # 如果是可见状态，切换为隐藏状态（显示为圆点/星号）
            password_field.password = True
            # 更新图标为"eye-off"（闭眼图标，表示当前隐藏）
            icon_button.icon = "eye-off"

    def clear_text(self):
        pass

    def on_press_back_arrow(self):
        pass





############################################@DIALOG BOX most used functions##############################################
        # MDDialog box function 'dialog'

    def dialog1(self, text, title="Tips"):
        close_button = MDFlatButton(
        text="关闭",
        font_name="MPoppins",
        on_release=self.close_dialog
    )
        
        content_label = Label(
            text=text,
            font_name="MPoppins",
            color=(0, 0, 0, 1),
            size_hint_y=None,
            height=dp(30),
            halign="center",
            valign="middle"
        )
        content_label.bind(size=content_label.setter('text_size'))

        self.dialog = MDDialog(
            title=title,
            type="custom",
            content_cls=content_label,
            size_hint=(0.84, None),
            buttons=[close_button]
        )
        self.dialog.open()
    def dialog2(self, title, text):
        close_button = MDFlatButton(
        text="关闭",
        font_name="MPoppins",
        on_release=self.close_dialog
    )
        
        content_label = Label(
            text=text,
            font_name="MPoppins",
            color=(0, 0, 0, 1),
            size_hint_y=None,
            height=dp(30),
            halign="center",
            valign="middle"
        )
        content_label.bind(size=content_label.setter('text_size'))

        self.dialog = MDDialog(
            title=title,
            type="custom",
            content_cls=content_label,
            size_hint=(0.84, None),
            buttons=[close_button]
        )
        self.dialog.open()



    # MDDialog box dismiss function 'close_dialog'
    def close_dialog(self, *args):
        self.dialog.dismiss()



#############################################Modbus Functions############################################################
    def show_modify_dialog(self, label_id, current_value=""):
        """显示修改对话框"""
        if not self.dialog2:
            # 创建输入框
            self.modify_input = MDTextField(
                id="modify_input",
                hint_text="请输入新值",
                input_filter="int",  # 保持整数输入限制
                text=current_value
            )

            # 创建对话框
            self.dialog2 = MDDialog(
                title="修改参数",
                type="custom",
                content_cls=MDBoxLayout(
                    self.modify_input,
                    orientation="vertical",
                    padding=dp(10),
                    spacing=dp(10),
                    size_hint_y=None,
                    height=dp(100)
                ),
                buttons=[
                    MDFlatButton(
                        text="取消",
                        on_press=lambda x: self.dialog2.dismiss()
                    ),
                    MDFlatButton(
                        text="确认",
                        on_press=lambda x: self.confirm_modify(label_id)
                    )
                ]
            )
        else:
            # 重置输入框内容
            self.modify_input.text = current_value
        
        self.dialog2.open()

    def confirm_modify(self, label_id):
        """确认修改并更新标签，增强鲁棒性"""
        try:
            new_value = self.modify_input.text
            if not new_value:
                self.show_dialog("错误", "请输入新值")
                return

            screen = self.root.get_screen("real_time_curve")
            label = screen.ids.get(label_id, None)
            if label:
                label.text = f"通信超时: {new_value}"
                # 调用原有的修改方法，增加异常捕获
                try:
                    self.modify_register(new_value)
                except Exception as e:
                    self.show_dialog("错误", f"寄存器修改失败：{e}")
            else:
                self.show_dialog("错误", "未找到目标标签")
        except Exception as e:
            self.show_dialog("错误", f"操作异常：{e}")
        finally:
            if self.dialog2:
                self.dialog2.dismiss()

    def read_modbus_registers(self, slave_id=1, address=0, count=1):
        """
        通用的Modbus保持寄存器读取函数
        :param slave_id: 从机ID
        :param address: 寄存器地址
        :param count: 读取数量
        :return: {'success': bool, 'data': list, 'msg': str}
        """
        return self.modbus_master.read_holding_registers(slave_id, address, count)

    def modify_register(self, field_widget, input_text):
        """
        用户主动修改时，写入指定寄存器并刷新显示
        :param field_widget: MDTextField控件对象
        :param input_text: 用户输入的值
        """
        address = getattr(field_widget, 'comm_address', None)
        slave_id = 1  # 可根据实际情况动态获取
        if address is None:
            self.show_dialog("错误", "未设置通讯地址")
            return
        if not input_text:
            self.show_dialog("错误", "请输入值")
            return
        try:
            value = int(input_text)
            result = self.write_modbus_register(slave_id=slave_id, address=address, value=value)
            # self.show_dialog("操作结果", result)
            self.update_register_display(0)
        except ValueError:
            self.show_dialog("错误", "请输入有效整数")

    def write_modbus_register(self, slave_id=1, address=0, value=None):
        """
        通用写入Modbus保持寄存器(单个寄存器)
        :param slave_id: 从机ID
        :param address: 寄存器地址
        :param value: 要写入的值(整数,0-65535)
        :return: {'success': bool, 'msg': str}
        """
        return self.modbus_master.write_single_register(slave_id, address, value)

    def show_dialog(self, title, message):
        self.dialog1(message,title)

    def update_register_display(self, dt):
        real_time_screen = self.root.get_screen("real_time_curve")
        widgets = [w for w in real_time_screen.ids.values() 
                   if isinstance(w, MDTextField) and hasattr(w, 'comm_address')]

        # 收集未聚焦的寄存器地址
        addr_widget_map = {}
        for w in widgets:
            if not w.focus:
                addr = getattr(w, 'comm_address', None)
                if addr is not None:
                    addr_widget_map[addr] = w

        if not addr_widget_map:
            return

        # 分组连续地址段（例如 [1,2,3,10,11,12] -> [[1,2,3], [10,11,12]])
        sorted_addresses = sorted(addr_widget_map.keys())
        grouped_ranges = []
        group = [sorted_addresses[0]]

        for addr in sorted_addresses[1:]:
            if addr == group[-1] + 1:
                group.append(addr)
            else:
                grouped_ranges.append(group)
                group = [addr]
        grouped_ranges.append(group)

        # 开启线程异步读取每段
        for group in grouped_ranges:
            start = group[0]
            count = group[-1] - start + 1
            thread = Thread(target=self._read_and_update_range, args=(start, count, group, addr_widget_map))
            thread.start()

    def _read_and_update_range(self, start, count, group, addr_widget_map):
        try:
            result = self.read_modbus_registers(slave_id=1, address=start, count=count)
        except Exception as e:
            result = {'success': False, 'error': str(e)}

        # 在主线程中更新 UI
        Clock.schedule_once(partial(self._update_widgets_with_data, start, group, addr_widget_map, result), 0)

    def _update_widgets_with_data(self, start, group, addr_widget_map, result, dt):
        if result.get('success') and result.get('data'):
            data = result['data']
            for addr in group:
                widget = addr_widget_map.get(addr)
                index = addr - start
                if widget and 0 <= index < len(data):
                    new_value = str(data[index])
                    if widget.text != new_value:
                        widget.text = new_value
                elif widget:
                    widget.text = "索引错误"
        else:
            for addr in group:
                widget = addr_widget_map.get(addr)
                if widget:
                    widget.text = f"失败: {result.get('error', '读取失败')}"

###################################LoginPageWork-Start#################################################

    def update_wifi_status(self, dt):
        # 只有当前屏幕为 login 时才更新
        if self.root.current != "login":
            return

        if platform != 'android':
            self.wifi_status_text = '非Android设备'
            return

        try:
            from jnius import autoclass, cast

            PythonActivity = autoclass('org.kivy.android.PythonActivity')
            Context = autoclass('android.content.Context')
            activity = PythonActivity.mActivity

            WifiManager = autoclass('android.net.wifi.WifiManager')
            Formatter = autoclass('android.text.format.Formatter')

            wifi_service = activity.getSystemService(Context.WIFI_SERVICE)
            wifi_manager = cast('android.net.wifi.WifiManager', wifi_service)

            if not wifi_manager.isWifiEnabled():
                self.wifi_status_text = 'WiFi 未启用'
                return

            wifi_info = wifi_manager.getConnectionInfo()
            if wifi_info is None:
                self.wifi_status_text = 'WiFi 信息不可用'
                return

            ssid = wifi_info.getSSID()
            ssid_display = ssid.strip('"') if ssid else "SSID Unknown"

            ip_int = wifi_info.getIpAddress()
            ip_str = Formatter.formatIpAddress(ip_int) if ip_int != 0 else "0.0.0.0"
            link_speed = wifi_info.getLinkSpeed()  # Mbps
            bssid = wifi_info.getBSSID()
            rssi = wifi_info.getRssi()

            self.wifi_status_text = (
                f'SSID: {ssid_display}\n'
                f'IP: {ip_str}\n'
                f'速度: {link_speed} Mbps\n'
                f'BSSID: {bssid}\n'
                f'信号: {rssi} dBm'
            )

        except Exception as e:
            self.wifi_status_text = f'获取WiFi信息失败\n{e}'

    def verify(self, obj=None):
        try:
            if platform == "android":
                from jnius import autoclass
                PythonActivity = autoclass('org.kivy.android.PythonActivity')
                Context = autoclass('android.content.Context')
                activity = PythonActivity.mActivity
                wifi_service = activity.getSystemService(Context.WIFI_SERVICE)
                wifi_info = wifi_service.getConnectionInfo()
                # 获取当前连接的WiFi名称并处理引号和大小写
                wifi_id = wifi_info.getSSID().strip('"').lower()
            else:
                # 非Android平台使用模拟WiFi
                wifi_id = "zhizhan-2"
        except Exception as e:
            self.dialog1(f"获取WiFi信息失败:{e}")
            return

        try:
            with open("data/Users.csv", "r", encoding="utf-8") as file:
                # 使用DictReader读取CSV，通过列名访问数据
                csv_reader = csv.DictReader(file)
                
                for row in csv_reader:
                    # 获取CSV中存储的WiFi SSID并处理大小写
                    csv_ssid = row['Wifi_SSID'].strip().lower()
                    
                    # 精确匹配WiFi SSID
                    if wifi_id == csv_ssid:
                        # 通过列名获取用户信息
                        name = row['User']
                        password = row['User_pass']
                        wifi_ssid = row['Wifi_SSID']
                        modbus_ip = row['Modbus_IP']
                        modbus_port = row['Modbus_Port']
                        nfc_id = row['NFC_ID']
                        reserve = row['Reserve']

                        # 更新界面显示的用户信息
                        self.root.current = "home"
                        self.user.text = f"[b]Hey! {name}[/b]"

                        self.profile_user_name.text = self.edit_user_name.text = name
                        self.profile_user_pass.text = self.edit_user_pass.text = password
                        self.profile_wifi_ssid.text = self.edit_wifi_ssid.text = wifi_ssid
                        self.profile_modbus_ip.text = self.edit_modbus_ip.text = modbus_ip
                        self.profile_modbus_port.text = self.edit_modbus_port.text = modbus_port
                        self.profile_nfc_id.text = self.edit_nfc_id.text = nfc_id
                        self.profile_reserve.text = self.edit_reserve.text = reserve


                        # 连接Modbus设备
                        self.connect_modbus()
                        self.dialog1(f"欢迎你，{name}!\n认证成功!")
                        return
        except Exception as e:
            self.dialog1(f"读取用户信息失败：{e}")
            return

        # 认证失败提示
        self.dialog1("认证失败,请检查网络或确保手机权限打开定位和连接到目标WiFi")

    def connect_modbus(self):
        def _connect_in_background():
            modbus_ip = None
            modbus_port = 502
            master = None

            try:
                # 获取当前WiFi SSID
                if platform == "android":
                    from jnius import autoclass
                    PythonActivity = autoclass('org.kivy.android.PythonActivity')
                    Context = autoclass('android.content.Context')
                    activity = PythonActivity.mActivity
                    wifi_service = activity.getSystemService(Context.WIFI_SERVICE)
                    wifi_info = wifi_service.getConnectionInfo()
                    current_wifi_id = wifi_info.getSSID().strip('"').lower()
                else:
                    current_wifi_id = "zhizhan-2"

                # 读取CSV配置
                with open("data/Users.csv", "r", encoding="utf-8") as file:
                    csv_reader = csv.DictReader(file)
                    for row in csv_reader:
                        csv_ssid = row['Wifi_SSID'].strip().lower()
                        if current_wifi_id == csv_ssid:
                            modbus_ip = row['Modbus_IP']
                            modbus_port = int(row['Modbus_Port']) if row['Modbus_Port'] else 502
                            break

                if not modbus_ip:
                    Clock.schedule_once(lambda dt: self.dialog1("未找到匹配的Modbus配置"))
                    return

                # 断开现有连接
                self.modbus_master.disconnect()

                # 创建新连接并测试
                connect_result = self.modbus_master.connect(modbus_ip, modbus_port)
                if not connect_result['success']:
                    Clock.schedule_once(lambda dt: self.dialog1(connect_result['msg']))
                    return
                print(f"Modbus连接成功\nIP: {modbus_ip}\n端口: {modbus_port}")
                # Clock.schedule_once(lambda dt: self.dialog1(f"Modbus连接成功\nIP: {modbus_ip}\n端口: {modbus_port}"))

            except FileNotFoundError as e:
                # 修复：将异常信息转为字符串或通过默认参数传递
                err_msg = "配置文件 Users.csv 未找到"
                Clock.schedule_once(lambda dt, msg=err_msg: self.dialog1(msg))
            except modbus_tk.modbus.ModbusError as e:
                # 修复：使用默认参数传递异常信息
                err_msg = f"Modbus协议错误: {e}\n从站地址: {e.slave}\n功能码: {e.function_code}"
                Clock.schedule_once(lambda dt, msg=err_msg: self.dialog1(msg))
                self.modbus_master = None
            except socket.error as e:
                err_msg = f"网络连接失败: {e}"
                Clock.schedule_once(lambda dt, msg=err_msg: self.dialog1(msg))
                self.modbus_master = None
            except Exception as e:
                # 修复：捕获所有其他异常
                err_msg = f"连接失败: {str(e)}"
                Clock.schedule_once(lambda dt, msg=err_msg: self.dialog1(msg))
                self.modbus_master = None

        threading.Thread(target=_connect_in_background, daemon=True).start()

    def edit_profile(self):
        if self.edit_user_name.text == "" or self.edit_user_pass.text == "" or self.edit_wifi_ssid.text == "" or self.edit_modbus_ip.text == "" or self.edit_modbus_port.text == "" or self.edit_nfc_id.text == "" or self.edit_reserve.text == "":
            check = "Enter all required fields"
            return self.dialog1(check)
        else:
            user_data = {
                'User': self.edit_user_name.text,
                'User_pass': self.edit_user_pass.text,
                'Wifi_SSID': self.edit_wifi_ssid.text,
                'Modbus_IP': self.edit_modbus_ip.text,
                'Modbus_Port': self.edit_modbus_port.text,
                'NFC_ID': self.edit_nfc_id.text,
                'Reserve': self.edit_reserve.text
            }
            update_user_profile(user_data, self.profile_wifi_ssid.text)
            self.verify(True)
            self.root.current = "home"

    def secure_profile(self):
        self.profile_edit_screen.ids.edit_user_pass.readonly = True
        self.profile_edit_screen.ids.edit_wifi_ssid.readonly = True
        self.profile_edit_screen.ids.edit_modbus_ip.readonly = True
        self.profile_edit_screen.ids.edit_modbus_port.readonly = True
        self.profile_edit_screen.ids.edit_nfc_id.readonly = True
        self.profile_edit_screen.ids.edit_reserve.readonly = False



from user_data_manager import update_user_profile

if __name__ == '__main__':
    app().run()



