# /*
#  * Copyright (C) 2020, KylinSoft Co., Ltd.
#  *
#  * 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/>.
#  */

import os
import time
from SystemUpdater.modules.i18n import _
import logging
import subprocess
from SystemUpdater.configs import G_settings
from typing import Optional

class PlymouthManager():
    def __init__(self):
        self.has_started = False
        self.last_mapped_progress = 0  # 记录上一次进度值

    def update(
        self,
        progress: Optional[int] = None,
        message: Optional[str] = None,
        range_min: int = 0,
        range_max: int = 100,
    ):
        """
        更新进度与消息。
        
        参数:
            progress: 逻辑进度 (0-100)
            message: 显示提示文本
            range_min: 当前进度显示的起始值
            range_max: 当前进度显示的结束值
        """
        if G_settings.get("prohibit_shutdown",False):
            return

        if not self.has_started:
            self.show()

        if progress is not None:
            # 限制逻辑进度范围
            progress = max(0, min(100, progress))

            # 区间映射计算
            mapped_progress = int(range_min + (progress / 100.0) * (range_max - range_min))

            # 避免重复执行相同进度命令
            if mapped_progress != self.last_mapped_progress:
                self.last_mapped_progress = mapped_progress
                run_cmd = ["/bin/plymouth", "system-update", f"--progress={mapped_progress}"]
                subprocess.call(run_cmd)

            if message is not None:
                subprocess.call(["/bin/plymouth", "message", "--text", message])

    def message_to(self,message):
        subprocess.call(["/bin/plymouth", "message", "--text", message])

    def progress_to(self,progress):
        tmp = ("--progress=%d"%progress)
        run_cmd = ["/bin/plymouth","system-update",tmp]
        subprocess.call(run_cmd)

    def check_state(self):
        try:
            args = ["/bin/plymouth","--ping"]
            p = subprocess.run(args,timeout=2,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
            if p.returncode == 0:
                logging.info("Check: Plymouthd state start to success...")
            else:
                logging.info("Check: Plymouthd Failed to Boot and Restart boot up again...")
                self._start_plymouth_splash()
        except Exception as exc:
            logging.error(exc) 

    def show(self):
        try:
            if not self.has_started:
                if os.path.exists("/sbin/plymouthd"):
                    if not self._check_device_type():
                        args = ["/sbin/plymouthd", "--mode=shutdown","--attach-to-session","--kernel-command-line=splash plymouth.use-legacy-input"]
                    else:
                        os.environ["DISPLAY"] = ":0"
                        args = ["/sbin/plymouthd", "--mode=shutdown","--attach-to-session","--kernel-command-line=splash plymouth.use-legacy-input"]
                    logging.info("Running plymouth:%r",args)
                    subprocess.run(args,timeout=3)
                if os.path.exists("/bin/plymouth"):
                    subprocess.Popen(["/bin/plymouth", "show-splash","--wait"])
            # 标识Plymouth界面已经启动 不需要再次开启
            self.has_started = True
            
            self.echo_log_to_tty("/var/log/ostree.log")
        except Exception as exc:
            logging.error(exc)

    def quit_retain(self):
        if os.path.exists("/bin/plymouth"):
            subprocess.run(["/bin/plymouth","quit","--retain-splash"])

    def _check_device_type(self):
        try:
            with open("/proc/cpuinfo", 'r') as f:
                for line in f.readlines():
                    if "Hardware" in line and ":" in line:
                        cpuinfos = line.split(':')
                        if "PANGU M900" in cpuinfos[1]:
                            logging.info("Get cpuinfo: PANGU M900")
                            return True
        except Exception as exc:
            logging.error(exc)
        return False
    
    @staticmethod
    def show_countdown(success,reboot_required):
        if G_settings.get("prohibit_shutdown",False):
            return
        
        try:
            state = "reboot" if reboot_required else "shutdown"
            success_msg = "The system update is successful and your computer will %s "%state + "in %s s"
            failed_msg = "System update is abnormal and your computer will %s "%state + "in %s s"
            if success:
                msg = _(success_msg)
            else:
                msg = _(failed_msg)

            for i in range(5, 0, -1):
                msges = msg%str(i)
                subprocess.call(["/bin/plymouth", "message", "--text", msges])
                time.sleep(1)
                logging.info(msges)
        except Exception as exc:
            logging.error(exc)

    def echo_log_to_tty(self, log_file):
        try:
            ECHO_DETAILS_LOG_DEST = "/dev/tty63"
            command = ["tail", "-f", log_file]
            with open(ECHO_DETAILS_LOG_DEST, "w") as output:
                # 将命令放入后台运行
                process = subprocess.Popen(command, stdout=output, stderr=subprocess.STDOUT)
        except Exception as exc:
            logging.error(exc)

    def clean_all(self):
        self.message_to("")
        self.progress_to(0)
