import logging
import os
import shutil
import psutil
import pathlib
import aiohttp
from voluptuous.schema_builder import message
from cbpi.api.dataclasses import NotificationAction, NotificationType
from cbpi.api.base import CBPiBase
from cbpi.api.config import ConfigType
from cbpi.api import *
import zipfile
import socket

class SystemController:

    def __init__(self, cbpi):
        self.cbpi = cbpi
        self.service = cbpi.actor
        self.logger = logging.getLogger(__name__)

        self.cbpi.app.on_startup.append(self.check_for_update)


    async def check_for_update(self, app):
        pass

    async def restart(self):
        logging.info("RESTART")
        os.system('systemctl reboot') 
        pass

    async def shutdown(self):
        logging.info("SHUTDOWN")
        os.system('systemctl poweroff') 
        pass

    async def backupConfig(self):
        output_filename = "cbpi4_config"
        dir_name = pathlib.Path(os.path.join(".", 'config'))
        shutil.make_archive(output_filename, 'zip', dir_name)

    def allowed_file(self, filename, extension):
        return '.' in filename and filename.rsplit('.', 1)[1] in set([extension])

    def recursive_chown(self, path, owner, group):
        for dirpath, dirnames, filenames in os.walk(path):
            shutil.chown(dirpath, owner, group)
            for filename in filenames:
                shutil.chown(os.path.join(dirpath, filename), owner, group)

    async def restoreConfig(self, data):
        fileData = data['File']
        filename = fileData.filename
        backup_file = fileData.file
        content_type = fileData.content_type
        required_content=['dashboard/', 'recipes/', 'upload/', 'config.json', 'config.yaml']

        if content_type == 'application/x-zip-compressed':
            try:
                content = backup_file.read()
                if backup_file and self.allowed_file(filename, 'zip'):
                    self.path = os.path.join(".", "restored_config.zip")

                    f=open(self.path, "wb")
                    f.write(content)
                    f.close()
                    zip=zipfile.ZipFile(self.path)
                    zip_content_list = zip.namelist()
                    zip_content = True
                    for content in required_content:
                        try:
                            check = zip_content_list.index(content)
                        except:
                            zip_content = False
                    if zip_content == True:
                        self.cbpi.notify("Success", "Config backup has been uploaded", NotificationType.SUCCESS)
                        self.cbpi.notify("Action Required!", "Please restart the server", NotificationType.WARNING)
                    else:
                        self.cbpi.notify("Error", "Wrong content type. Upload failed", NotificationType.ERROR)
                        os.remove(self.path)
            except:
                self.cbpi.notify("Error", "Config backup upload failed", NotificationType.ERROR)
                pass
        else:
            self.cbpi.notify("Error", "Wrong content type. Upload failed", NotificationType.ERROR)

    async def systeminfo(self):
        logging.info("SYSTEMINFO")
        system = "" 
        temp = 0
        cpuload = 0
        cpucount = 0
        cpufreq = 0
        totalmem = 0
        availmem = 0
        mempercent = 0
        eth0IP = "N/A"
        wlan0IP = "N/A"

        TEMP_UNIT=self.cbpi.config.get("TEMP_UNIT", "C")
        FAHRENHEIT = False if TEMP_UNIT == "C" else True

        af_map = { socket.AF_INET: 'IPv4',
                   socket.AF_INET6: 'IPv6',
                   }

        try:
            if psutil.LINUX == True:
                system = "Linux"
            elif psutil.WINDOWS == True:
                system = "Windows"
            elif psutil.MACOS == True:
                system = "MacOS"
            cpuload = round(psutil.cpu_percent(interval=None),1)
            cpucount = psutil.cpu_count(logical=False)
            cpufreq = psutil.cpu_freq()
            mem = psutil.virtual_memory()
            availmem = round((int(mem.available) / (1024*1024)),1)
            mempercent = round(float(mem.percent),1)
            totalmem = round((int(mem.total) / (1024*1024)),1)
            if system == "Linux":
                try:
                    temps = psutil.sensors_temperatures(fahrenheit=FAHRENHEIT)
                    for name, entries in temps.items():
                        for entry in entries:
                            if name == "cpu_thermal":
                                temp = round(float(entry.current),1)
                except:
                    pass
            else:
                temp = "N/A"
            if system == "Linux":
                try:
                    ethernet = psutil.net_if_addrs()
                    for nic, addrs in ethernet.items():
                        if nic == "eth0":
                            for addr in addrs:
                                if str(addr.family) == "AddressFamily.AF_INET": 
                                    if addr.address:
                                        eth0IP = addr.address
                        if nic == "wlan0":
                            for addr in addrs:
                                if str(addr.family) == "AddressFamily.AF_INET": 
                                    if addr.address:
                                        wlan0IP = addr.address
                except:
                    pass

        except:
            pass

        systeminfo =    {'system': system,
                         'cpuload': cpuload,
                         'cpucount': cpucount,
                         'cpufreq': cpufreq.current,
                         'totalmem': totalmem,
                         'availmem': availmem,
                         'mempercent': mempercent,
                         'temp': temp,
                         'temp_unit': TEMP_UNIT,
                         'eth0': eth0IP,
                         'wlan0': wlan0IP}
        return systeminfo