import sys

import string
import re
import socket
import asyncio
import os
import psutil
import socket
from dns import resolver

from ...docker.client import DockerClient
from ..base import Base

class Base_service(Base):
    def preload(self):
        self.dockercli = DockerClient.from_env();

    def status_host_port(self,*args):
        host = args[0].CS_RABBIT_HOST[-1]
        port = int(args[0].CS_RABBIT_PORT[-1])
        msg = ""
        self.logger.error(f'Тест доступности по пингу и порту: {host}:{port}')
        try:
            con = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            con.settimeout(2)
            con.connect((host, port))
        except socket.gaierror as e:
            self.logger.error(f"Ошибка DNS при разрешении имени хоста {host}: {e}\n")
            msg = f"Ошибка DNS при разрешении имени хоста {host}: {e}\n"
        except TimeoutError as e:
            msg = f"Истекло время ожидания при подключении к {host}:{port}: {e}\n"
            self.logger.error(f"Истекло время ожидания при подключении к {host}:{port}: {e}\n")
        except ConnectionRefusedError as e:
            msg = f"Соединение отклонено хостом {host}:{port}: {e}\n"
            self.logger.error(f"Соединение отклонено хостом {host}:{port}: {e}\n")
        except OSError as e:
            msg = f"Ошибка ОС/сокета при подключении к {host}:{port}: {e}\n"
            self.logger.error(f"Ошибка ОС/сокета при подключении к {host}:{port}: {e}\n")
        except Exception as e:
            msg = f"Неожиданная ошибка при подключении к {host}:{port}: {e}\n"
            self.logger.error(f"Неожиданная ошибка при подключении к {host}:{port}: {e}\n")
        else:
            msg = f"Подключено: , {con}\n"
            self.logger.error("Подключено\n")
        finally:
            if con:
                try:
                    con.close()
                except Exception:
                    pass        # print(conn)
        return msg
    
    def status_proc(self,count):
        answer = ""
        i = count
        if os.cpu_count() >= i:
            answer = "OK"
        else:
            answer = "BAD"
        num_cores = "Процессор на "+str(os.cpu_count())+" ядер  - "+answer+"\n"
        return num_cores
    
    def status_ram(self,countr):
        r = countr
        memory = []
        answer = ""
        if (psutil.virtual_memory().total / (1024**3)) >= r:
            answer = "OK"
        else:
            answer = "BAD"
        memory.append(f"Общая память: {psutil.virtual_memory().total / (1024**3):.2f} ГБ - {answer}\n")
#        memory.append(f"Использованная память: {psutil.virtual_memory().used / (1024**3):.2f} ГБ\n")
#        memory.append(f"Свободная память: {psutil.virtual_memory().free / (1024**3):.2f} ГБ\n")
        mem = memory[0]#+memory[1]+memory[2]
        return mem

    def status_dns(self,*args):
        msg = []
        msg2 = ""
        for dns in args:
            try:
                ip = socket.gethostbyname(dns)
                msg.append(f"DNS-имя '{dns}' успешно резолвится в IP: {ip}\n")
                msg2 = msg2 + f"DNS-имя '{dns}' успешно резолвится в IP: {ip}\n"
            except socket.gaierror:
                msg.append(f"DNS-имя '{dns}' не найдено.\n")
                msg2 = msg2 + f"DNS-имя '{dns}' не найдено.\n"
            except Exception as e:
                msg.append(f"Произошла ошибка при проверке '{dns}': {e}\n")
                msg2 = msg2 + f"Произошла ошибка при проверке '{dns}': {e}\n"
#            print(msg)
        return msg2
    
    def status_hdd(self):
#         msg = ""
#         for part in psutil.disk_partitions():
#             mounts = psutil.disk_usage(part.mountpoint)
#             print(f"раздел {part.mountpoint}")
# #            msg = msg + f"раздел {part.mountpoint}\nвсего: {mounts.total}\nсвободно {mounts.free}\nиспользовано {mounts.used}\nиспользовано {mounts.percent} %\n"
#             msg = msg + f"раздел {part.mountpoint}\nвсего: {mounts.total / (1024 ** 3)}\nсвободно {mounts.free / (1024 ** 3)}\nиспользовано {mounts.percent} %\n"
        msg = ""
        answer = ""
        mounts = psutil.disk_usage("/")
        if (mounts.free / (1024 ** 3)) > 65:
            answer = "Дискового пространства достаточно"
        else:
            answer = "Дискового пространства не достаточно"

        print(f"раздел /")
        msg = msg + f"раздел /\nвсего: {mounts.total / (1024 ** 3)}\nсвободно {mounts.free / (1024 ** 3)}\nиспользовано {mounts.percent} %\n{answer}"
        return msg
        
    def env_is_default(self, env_name):
        if isinstance(env_name, list):
            for env in env_name:
                if len(getattr(self, env)) != 2: getattr(self, env).insert(1, getattr(self, env)[0])
        else:
            if len(getattr(self, env_name)) != 2: getattr(self, env_name).insert(1, getattr(self, env_name)[0])

    def env_is_unselect(self, env_name):
        if isinstance(env_name, list):
            for env in env_name:
                del(getattr(self, env_name)[1]);
        else:
            del(getattr(self, env_name)[1]);

    def get_constants(self):
        return dict(filter(lambda item: item[0]==item[0].upper(), vars(self).items()));

    def load_images(self, images: list = [], **kwarg):
        outputs=[];
        self.logger.info(f'Начинаю импорт дампа образов: {kwarg.get("images")}')
        for image in kwarg.get('images'):
            self.logger.debug(f'Открываю файл дампа: {self.INSTALL_DUMP_PATH}/{image}')
            with open(f'{self.INSTALL_DUMP_PATH}/{image}', 'rb') as file:
                self.logger.info(f'Загружаю dump образов: {self.INSTALL_DUMP_PATH}/{image}')
                print(f'\nЗагружаю dump образов:\n{self.INSTALL_DUMP_PATH}/{image}\n');
                try:
                    outputs = outputs + self.dockercli.images.load(file);
                except:
                    self.logger.error(f'Произошла ошибка при загрузке docker-образов из dump-файла: {image}')
                    self.msgbox(f'Произошла ошибка при загрузке docker-образов из dump-файла {image}.');

    async def load_images_async(self, **kwarg):
        outputs=[];
        self.logger.info(f'Начинаю импорт дампа образов: {kwarg.get("images")}')
        for image in kwarg.get('images'):
            self.logger.debug(f'Открываю файл дампа: {self.INSTALL_DUMP_PATH}/{image}')
            if os.path.isfile(f'{self.INSTALL_DUMP_PATH}/{image}'):
                with open(f'{self.INSTALL_DUMP_PATH}/{image}', 'rb') as file:
                    self.logger.info(f'Загружаю dump образов: {self.INSTALL_DUMP_PATH}/{image}')
                    try:
                        outputs = outputs + self.dockercli.images.load(file);
                    except:
                        self.logger.error(f'Произошла ошибка при загрузке docker-образов из dump-файла: {image}')
                        return self.msgbox(f'Произошла ошибка при загрузке docker-образов из dump-файла {image}.');
            else:
                self.logger.error(f'Файл dump образов отсутствует: {self.INSTALL_DUMP_PATH}/{image}')

    async def async_run(self, tasks:list = [], **kwarg):
        self.logger.debug(f'Назначены функции к выполнению: {tasks} и список переменных: {kwarg}')
        for index, func in enumerate(tasks):
            self.logger.debug(f'Добавляю задание к выполнению на функцию {func}')
            tasks[index]=asyncio.ensure_future(func(**kwarg))
        self.logger.debug(f'Запускаю корутину со списком заданий')
        for future in asyncio.as_completed(tasks):
            self.logger.debug(f'Ожидаю получения футуры')
            callback = await future
            if callable(callback):
                self.logger.debug(f'Получена футура с функцией обратного вызова. Произвожу запуск функции.')
                callback()
            else:
                self.logger.debug(f"Футура получена {callback if callback else ''}")
                return callback

    def async_runner(self, tasks:list = [], **kwarg):
        self.logger.info(f'Начинаю выполнение корутины async_run и жду выполнения...')
        self.loop.run_until_complete(self.async_run(tasks=tasks, **kwarg))
        self.logger.info(f'Корутина async_run выполнена')

    def get_service(self):
        if self.BACK_MENU[0]==True:
            return        
        return self.service

    def get_external_class(self, external_class):
#        external_class = getattr(globals()[module_name], class_name)
        with external_class(**dict(filter(lambda item: item[0]==item[0].upper(), vars(self).items())), select_components = self.select_components, logger_level = self.logger_level) as run:
            run.go(external = True);
            for name, value in run.get_constants().items():
                setattr(self, name, value);

#    def callback(self):
#        return {"environment": self.get_constants(), "service": {self.__class__.__name__: self.add_service()}};
    def visibility_default(self, default:bool = True):
        return lambda request: default
    def visibility_detalization(self, detalization: int = 1):
        return lambda request: True if (request.get("detalization") <= self.DETALIZATION if isinstance(request.get("detalization"),int) else detalization <= self.DETALIZATION) else False
    def check_default(self):
        return lambda response, env: (True, None)
    def check_hostname(self):
        def func(response, env):
#Проверка IP
#            if env.get('allow_ip'):
            if True:
                try:
                    socket.inet_pton(socket.AF_INET, response)
                    return (True, None)
                except (socket.error, ValueError):
                    pass
                try:
                    socket.inet_pton(socket.AF_INET6, response)
                    return (True, None)
                except (socket.error, ValueError):
                    pass
#Проверка Hostname
            parts = response.split('.')
            if len(parts[0]) < 2 or len(parts[0]) > 63:
                return (False, f"Hostname '{parts[0]}' имеет недопустимую длину (должно быть от 2 до 63 символов)")
            if not re.match(r'^[a-z0-9-]+$', parts[0]):
                return (False, f"Hostname '{parts[0]}' содержит недопустимые символы (только буквы, цифры и дефисы)")
            if parts[0].startswith('-') or parts[0].endswith('-'):
                return (False, f"Hostname '{parts[0]}' не может начинаться или заканчиваться дефисом")
            if '--' in parts[0]:
                return (False, f"Hostname '{parts[0]}' не может содержать два дефиса подряд")
            if len(parts)>1:
                for part in parts[1:]:
                    if len(part) < 2 or len(part) > 63:
                        return (False, f"Доменная часть '{part}' имеет недопустимую длину (должно быть от 2 до 63 символов)")
                    if not re.match(r'^[a-z0-9-]+$', part):
                        return (False, f"Доменная часть '{part}' содержит недопустимые символы (только буквы, цифры и дефисы)")
                    if part.startswith('-') or part.endswith('-'):
                        return (False, f"Доменная часть '{part}' не может начинаться или заканчиваться дефисом")
                    if '--' in part:
                        return (False, f"Доменная часть '{part}' не может содержать два дефиса подряд")
            return (True, None)
        return func
#        return lambda response, env: (not any(char in string.punctuation.translate({ord('-'):' ',ord('.'):''}) for char in response), None)
    def check_container_name(self):
        return lambda response, env: (not any(char in string.punctuation.translate({ord('-'):' ',ord('_'):''}) for char in response), None)
    def check_image_tag(self):
        return lambda response, env: (not any(char in string.punctuation.translate({ord('-'):' ',ord(':'):'',ord('_'):'',ord('.'):'',ord('/'):''}) for char in response), None)
    def check_port(self):
        return lambda response, env: (not any(char not in string.digits for char in response), None)

    #str(gen_uuid)  #lambda response, env: (not any(char not in string.digits for char in response), None) 
    def check_user(self):
#        return lambda response, env: (not any(char in string.punctuation.translate({ord('-'):' ',ord('_'):''}) for char in response), None)
        return lambda response, env: (True, None) if (re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', response) and not response == '') else (False, f'Имя пользователя {response} не может быть пустым или содержать символы, отличные от A-z, 0-9 и "_"')
    def check_uid(self):
        return lambda response, env: (True, None) if (re.fullmatch(r'[a-zA-Z0-9-_][a-zA-Z0-9-_]*', response) and not response == '') else (False, f'UID {response} не может быть пустым или содержать символы, отличные от A-z, 0-9 и "_"')
    def check_pwd(self):
        return lambda response, env: (not response == '', None)
    def check_db(self):
        return lambda response, env: (True, None) if (re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', response) and not response == '') else (False, f'Имя базы данных {response} не может быть пустым или содержать символы, отличные от A-z, 0-9 и "_"')
#        return lambda response, env: (not any(char in string.punctuation.translate({ord('-'):' ',ord('_'):''}) for char in response), None)
    def check_file(self):
        return lambda response, env: (os.path.isfile(response), None)
    def check_dir(self):
        return lambda response, env: (os.path.isdir(response) and not any(char in ['*','%',';',',','\\'] for char in response), None)
    def check_domain(self):
        def func(response, env):
            parts = response.lower().split('.')
            for part in parts:
                if len(part) < 2 or len(part) > 63:
                    return (False, f'''Часть домена '{part}' имеет недопустимую длину (должно быть от 2 до 63 символов)''')
                if not re.match(r'^[a-z0-9-]+$', part):
                    return (False, f'''Часть '{part}' содержит недопустимые символы (только буквы, цифры и дефисы)''')
                if part.startswith('-') or part.endswith('-'):
                    return (False, f'''Часть '{part}' не может начинаться или заканчиваться дефисом''')
                if '--' in part:
                    return (False, f'''Часть '{part}' не может содержать два дефиса подряд''')
            return (True, None)
        return func
    def check_fqdn(self):
        def func(response, env):
            parts = response.lower().split('.')
            if len(parts) < 2:
                return (False, "FQDN-имя должно содержать hostname-часть и хотя бы одну доменную часть (минимум 2 части)")
            if len(parts[0]) < 2 or len(parts[0]) > 63:
                return (False, f"Hostname '{parts[0]}' имеет недопустимую длину (должно быть от 2 до 63 символов)")
            if not re.match(r'^[a-z0-9-]+$', parts[0]):
                return (False, f"Hostname '{parts[0]}' содержит недопустимые символы (только буквы, цифры и дефисы)")
            if parts[0].startswith('-') or parts[0].endswith('-'):
                return (False, f"Hostname '{parts[0]}' не может начинаться или заканчиваться дефисом")
            if '--' in parts[0]:
                return (False, f"Hostname '{parts[0]}' не может содержать два дефиса подряд")
            for part in parts[1:]:
                if len(part) < 2 or len(part) > 63:
                    return (False, f"Доменная часть '{part}' имеет недопустимую длину (должно быть от 2 до 63 символов)")
                if not re.match(r'^[a-z0-9-]+$', part):
                    return (False, f"Доменная часть '{part}' содержит недопустимые символы (только буквы, цифры и дефисы)")
                if part.startswith('-') or part.endswith('-'):
                    return (False, f"Доменная часть '{part}' не может начинаться или заканчиваться дефисом")
                if '--' in part:
                    return (False, f"Доменная часть '{part}' не может содержать два дефиса подряд")
            return (True, None)
        return func

    def check_name(self):
        return lambda response, env: (True, None) if len(response)>1 else (False, 'Имя не может быть пустым')

    def check_extended_dir(self):
        def func(response, env):
            if not response:
                return (False, 'Путь не может быть пустым')
            if any(char in response for char in ['\0', '<', '>', '|', ':', ';', '*', '?', '\\', '"', "'", '`', '$', '!', '\n', '\r']):
                return (False, f'Путь {response} содержит запрещенные символы')
            if os.path.isdir(response):
                if not os.access(response, os.W_OK):
                    return (False, f'Нет прав на запись в директорию {response}. Выберите другую директорию.')
                else:
                    return (True, None)
            else:
                if self.form.yesno(f'Директория {os.path.abspath(response)} не найдена\n\n Создать директорию?', default = "yes"):
                    try:
                        os.makedirs(response,exist_ok=True)
                        return (True, None)
                    except:
                        self.msgbox(f'Произошла ошибка при создании директории. Проверьте права доступа к ФС, либо выберите другую директорию.');
                        return (False, None)
                else:
                    return (False, None)

        return func
    
    def parse_default(self):
        return lambda response, env: response
    def parse_domain(self):
        return lambda response, env: response.lower()
    def parse_fqdn(self):
        return lambda response, env: response.lower().split('.', maxsplit=1) if isinstance(env, list) else tuple(response.lower().split('.', maxsplit=1));
    def parse_path_file(self):
        return lambda response, env: os.path.split(response) if isinstance(env, tuple) else list(os.path.split(response))
    def parse_path_dir(self):
        return lambda response, env: os.path.abspath(response)
    def parse_image_tag(self):
        return lambda response, env: response.lower().rsplit(':', maxsplit=1) if isinstance(env, list) else tuple(response.lower().rsplit(':', maxsplit=1))

    def get_request(self, env_name: str, enable: str, msg: tuple = ('Текст сообщения', 'Текст при отмене ввода', 'Текст при ошибке проверки ввода'), default = None, func_parse = lambda response, env: response, func_check = lambda response, env: True, password: bool = False):
        if self.BACK_MENU[0]==True:
            return
        self.logger.debug(f'Проверяю тип запрашиваемого значения')
        if isinstance (env_name, str):
            self.logger.debug(f'Тип запрашиваемого значения: {type(env_name)}')
            self.logger.debug(f'Проверяю было ли назначено раннее значение у переменной {env_name}')
            while len(getattr(self, env_name)) < 2:
                self.logger.debug(f'Значение у переменной {env_name} не было назначено ранее. Выполняю запрос переменной у пользователя.')
                response=self.inputbox(msg = msg[0], default = getattr(self, env_name)[0], password = password);
                if not response[1]:
                    self.logger.debug(f'Пользователь ввел: {response[0]}\nВызываю функцию проверки введенного значения.')
                    check, msg_check = func_check(response[0], env_name)
                    if check:
                        self.logger.debug(f'Проверка введенного значения пройдена')
                        if msg_check:
                            self.msgbox(msg_check);
                        if password:
                            self.logger.debug(f'Значение является паролем, запрашиваю у пользователя подтверждение.')
                            pwd_temp=response[0]
                            response=self.inputbox(msg=f'Введите подтверждение пароля:', default = default if default else getattr(self, env_name)[0], password = password);
                            if not response[1] and response[0] == pwd_temp:
                                self.logger.debug(f'Пароль подтвержден. Добавляю введенное значение в переменную {env_name}')
                                getattr(self, env_name).insert(1, func_parse(response[0], env_name));
                            else:
                                self.logger.debug(f'{"Пользователь нажал отмена. Запрашиваю переменную повторно." if response[1] else f"Пользователь ввел неверное подтверждение: {response[0]}. Запрашиваю переменную повторно."}')
                                self.msgbox(f'Пароль не подтвержден.\n Давайте попробуем еще раз.');
                                continue
                        else:
                            self.logger.debug(f'Добавляю введенное значение в переменную {env_name}')
                            #self.form.msgbox(func_parse(response[0], env_name));
                            getattr(self, env_name).insert(1, func_parse(response[0], env_name));
                            self.logger.debug(f'Текущее значение переменной {env_name}: {getattr(self, env_name)}')
                    else:
                        self.logger.debug(f'Введенное значение не прошло проверку. Вывожу сообщение пользователю о неверном значении. Запрашиваю переменную повторно.')
                        if msg_check:
                            self.msgbox(msg_check);
                        if msg[2]:
                            self.msgbox(msg[2]);
                        continue
                else:
                    self.logger.debug(f'Пользователь нажал отмена. Вывожу уведомление при отмене ввода: {msg[1]}')
#                    self.msgbox(msg[1]);
                    self.BACK_MENU[0]=True
                    return

        if isinstance (env_name, tuple) or isinstance (env_name, list):
            self.logger.debug(f'Тип запрашиваемого значения: {type(env_name)}')
            self.logger.debug(f'Проверяю были ли назначены раннее значения у переменных: {env_name}')
            self.logger.debug(f'Дамп значений:{[getattr(self, env_name[i]) for i in range(len(env_name))]}')
            while any([len(getattr(self, env_name[i])) < 2 for i in range(len(env_name))]):
                self.logger.debug(f'Значения у переменных {env_name} не были назначены. Выполняю запрос у пользователя.')
                response=self.inputbox(msg = msg[0], default = default if default else getattr(self, env_name)[0], password = password);
                if not response[1]:
                    self.logger.debug(f'Пользователь ввел: {response[0]}\nВызываю функцию проверки введенного значения.')
                    check, msg_check = func_check(response[0], env_name)
                    if check:
                        self.logger.debug(f'Проверка введенного значения пройдена')
                        if msg_check:
                            self.msgbox(msg_check);
                        if password:
                            self.logger.debug(f'Значение является паролем, запрашиваю у пользователя подтверждение.')
                            pwd_temp=response[0]
                            response=self.inputbox(msg=f'Введите подтверждение:', default = default if default else getattr(self, env_name)[0], password = password);
                            if not response[1] and response[0] == pwd_temp:
                                self.logger.debug(f'Пароль подтвержден. Вызываю функцию парсинга введенного значения: {response[0]}')
                                func_parse_result = func_parse(response[0], env_name);
                                self.logger.debug(f'Распарсенные значения: {func_parse_result}')
                                for index in range(len(func_parse_result)):
                                    self.logger.debug(f'Добавляю распарсенное значение: func_parse_result[index] в переменную {env_name[index]}')
                                    getattr(self, env_name[index]).insert(1, func_parse_result[index]);
                                    self.logger.debug(f'Дамп:\nenv: {getattr(self, env_name[index])}\nparse_value:{func_parse_result[index]}')
#                                    getattr(self, env_name[index]).append(func_parse_result[index]);
                            else:
                                self.msgbox(f'Введенные данные не подтверждены.\n Давайте попробуем еще раз.');
                                continue
                        else:
                            self.logger.debug(f'Вызываю функцию парсинга введенного значения: {response[0]}')
                            func_parse_result = func_parse(response[0], env_name);
                            self.logger.debug(f'Распарсенные значения: {func_parse_result}')
#                            print(response[0])
#                            print(func_parse_result)
                            for index in range(len(func_parse_result)):
                                self.logger.debug(f'Добавляю распарсенное значение: func_parse_result[index] в переменную {env_name[index]}')
                                getattr(self, env_name[index]).insert(1, func_parse_result[index]);
                                self.logger.debug(f'Дамп:\nenv: {getattr(self, env_name[index])}\nparse_value:{func_parse_result[index]}')
#                                getattr(self, env_name[index]).append(func_parse_result[index]);
                    else:
                        self.logger.debug(f'Введенное значение не прошло проверку. Вывожу сообщение пользователю о неверном значении. Запрашиваю переменную повторно.')
                        if msg_check:
                            self.msgbox(msg_check);
                        if msg[2]:
                            self.msgbox(msg[2]);
                        self.msgbox(msg[2]);
                        continue
                else:
                    self.logger.debug(f'Пользователь нажал отмена. Вывожу уведомление при отмене ввода: {msg[1]}')
#                    self.msgbox(msg[1]);
                    self.BACK_MENU[0]=True
                    return

#     def get_dialogs(self, dialogs):
#         count=0
#         n = len(dialogs)
#         while count < n:
#             request=dialogs[count]
#             if (request.get("func_visibility")(request) if callable(request.get("func_visibility")) else False) or (any([func(request) for func in request.get("func_visibility")]) if isinstance(request.get("func_visibility"),list) else False) or request.get("enable"):
#                 result=self.get_request(
#                     env_name = request["env"],
#                     default = request["default"] if request.get("default") else None,
#                     enable = request["enable"],
#                     msg = request['msg'],
#                     func_check = request["func_check"] if request.get("func_check") else self.check_default(),
#                     func_parse = request["func_parse"] if request.get("func_parse") else self.parse_default(),
#                     password = request["env"].endswith("_PWD") or request["env"].endswith("_KEY") if isinstance(request["env"],str) else False
#                 );
                
#             else:
#                 if isinstance(request["env"],str):
#                     if len(getattr(self, request["env"])) != 2: getattr(self, request["env"]).append(getattr(self, request["env"])[0]);
#                 else:
#                     for env in request["env"]:
#                         if len(getattr(self, env)) != 2: getattr(self, env).append(getattr(self, env)[0]);
#             if result != 2: 
#                 count += 1
# #            elif result == "repeat":
#                 # повторить ту же итерацию — i не меняется
# #                continue
#             else:
#                 return 2
#                 # возврат к предыдущей итерации
# #                count = max(0, count - 1)
#             # else:  # например "cancel" или ошибка — решите логику сами
#             #     i += 1


    def get_dialogs(self, dialogs):
        for request in dialogs:
            if (request.get("func_visibility")(request) if callable(request.get("func_visibility")) else False) or (any([func(request) for func in request.get("func_visibility")]) if isinstance(request.get("func_visibility"),list) else False) or request.get("enable"):
                self.get_request(
                    env_name = request["env"],
                    default = request["default"] if request.get("default") else None,
                    enable = request["enable"],
                    msg = request['msg'],
                    func_check = request["func_check"] if request.get("func_check") else self.check_default(),
                    func_parse = request["func_parse"] if request.get("func_parse") else self.parse_default(),
                    password = request["env"].endswith("_PWD") or request["env"].endswith("_KEY") if isinstance(request["env"],str) else False
                );
            else:
                if isinstance(request["env"],str):
                    if len(getattr(self, request["env"])) != 2: getattr(self, request["env"]).append(getattr(self, request["env"])[0]);
                else:
                    for env in request["env"]:
                        if len(getattr(self, env)) != 2: getattr(self, env).append(getattr(self, env)[0]);
            if self.BACK_MENU[0] == True:
                return

    def get_requests_generic(self, dialog: dict = None, external:bool = False):
        dialogs = dialog if isinstance(dialog, list) else [
            {
                "env": f'CS_FRONTEND_DOMAIN',
                "enable": True,
                "msg": (
                    f'Введите имя домена',
                    f'Имя домена обязательно к заполнению.',
                    None
#                    f'Имя домена не может содержать спецсимволы, кроме "-" и "."'
                ),
                "func_check": self.check_domain(),
                "func_parse": self.parse_default()
            },
        ];
        self.get_dialogs(dialogs);
        dialogs = [
            {
                "env": f'DS_FRONTEND_PREFIX_DOCSERVER',
                "enable": None,
                "msg": (
                    f'Р7-Сервер документов:\n\nВведите префикс для FQDN-имени сайта "Р7-Офис".\nТекущее назначенное имя: {self.DS_FRONTEND_PREFIX_DOCSERVER[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'DS_FRONTEND_PREFIX_DOCSERVER',
                "enable": None,
                "msg": (
                    f'Р7-Сервер документов:\n\nВведите префикс для FQDN-имени сайта "Р7-Офис".\nТекущее назначенное имя: {self.DS_FRONTEND_PREFIX_DOCSERVER[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_CDDISK',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Диск".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_CDDISK[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_ADMIN',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Панель управления".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_ADMIN[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_CDMAIL',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Почта".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_CDMAIL[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_CONTACTS',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Контакты".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_CONTACTS[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_CALENDAR',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Календарь".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_CALENDAR[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_PROJECTS',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Проекты".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_PROJECTS[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_DRAW',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Графика".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_DRAW[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_PAGES',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Страницы".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_PAGES[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },
            {
                "env": f'CS_FRONTEND_PREFIX_FORMS',
                "enable": None,
                "msg": (
                    f'Р7-Корпоративный сервер:\n\nВведите префикс для FQDN-имени сайта "Р7-Формы".\nТекущее назначенное имя: {self.CS_FRONTEND_PREFIX_FORMS[0]}.{self.CS_FRONTEND_DOMAIN[-1]}',
                    f'Префикс имени сайта обязателен к заполнению.',
                    f'Префикс не может содержать спецсимволы, кроме "-"'
                ),
                "func_check": self.check_hostname(),
                "func_visibility": [self.visibility_detalization()],
                "detalization": 2
            },

#            {
#                "env": f'DS_NODE_LICENSE_FILE',
#                "enable": None,
#                'msg': (
#                    f'Р7-Cервер документов:\n\nВведите путь до файла лицензии',
#                    f'Путь до файла лицензии обязателен к заполнению',
#                    f'Файл не найден'
#                ),
#                "func_parse": self.parse_path_dir(),
#                "func_check": self.check_extended_dir(),
#                "func_visibility": self.visibility_detalization(),
#                "detalization": 4
#            },
#            {
#                "env": ('CS_NODE_FRONTEND_CERT_CRT_PATH','CS_NODE_FRONTEND_CERT_CRT_FILE'),
#                "enable": True,
#                "msg": (
#                    f'Введите путь до файла SSL-сертификата',
#                    f'Путь до файла сертификата обязателен к заполнению.',
#                    f'Файл сертификата по указанному пути не найден.'
#                ),
#                "func_parse": self.parse_path_file(),
#                "func_check": self.check_file()
#            }
        ];
        self.get_dialogs(dialogs);
