from typing import List, Optional, Dict, Tuple, Union
from ..application.assembler import Assembler
from .entity import (
    APIGatewayBlacklistItem,
    APIGatewayRequest,
    BootstrapInfo,
    ClusterConfig,
    ClusterConfigData,
    Condition,
    DNSInventory,
    DatapipeDataInfo,
    DatapipeServerInfo,
    FileTemplateVariables,
    FilesTemplateVariables,
    NodeInventory,
    RandomTemplateVariables,
    RecoverSetting,
    SearchItem,
    SearchRequest,
    SearchResponse,
    TaskDeleteRequest,
    TaskDetail,
    TaskItem,
    TaskRequest
)
from .dto import (
    APIGatewayBlacklistItemDTO,
    APIGatewayRequestDTO,
    BootstrapInfoDTO,
    ClusterConfigDTO,
    ClusterConfigDataDTO,
    ConditionDTO,
    DNSInventoryDTO,
    DatapipeDataInfoDTO,
    DatapipeServerInfoDTO,
    FileTemplateVariablesDTO,
    FilesTemplateVariablesDTO,
    NodeInventoryDTO,
    RandomTemplateVariablesDTO,
    RecoverSettingDTO,
    SearchItemDTO,
    SearchRequestDTO,
    SearchResponseDTO,
    TaskDeleteRequestDTO,
    TaskDetailDTO,
    TaskItemDTO,
    TaskRequestDTO
)
from .value_obj import (
    K3SNodeType,
    Status,
    UDate,
    UDict,
    UInt,
    UStr
)



class ConditionAssembler(Assembler):
    def to_entity(self, dto: ConditionDTO):
        return Condition(
            min_cpu_num = None if dto.min_cpu_num is None else UInt(dto.min_cpu_num),
            max_cpu_num = None if dto.max_cpu_num is None else UInt(dto.max_cpu_num),
            min_memory_size = None if dto.min_memory_size is None else UInt(dto.min_memory_size),
            max_memory_size = None if dto.max_memory_size is None else UInt(dto.max_memory_size),
            min_gpu_num = None if dto.min_gpu_num is None else UInt(dto.min_gpu_num),
            max_gpu_num = None if dto.max_gpu_num is None else UInt(dto.max_gpu_num),
            min_gpu_memory_size = None if dto.min_gpu_memory_size is None else UInt(dto.min_gpu_memory_size),
            max_gpu_memory_size = None if dto.max_gpu_memory_size is None else UInt(dto.max_gpu_memory_size)
        )
    def to_dto(self, x:Condition):
        return ConditionDTO(
            min_cpu_num = None if x.min_cpu_num is None else x.min_cpu_num.get_value(),
            max_cpu_num = None if x.max_cpu_num is None else x.max_cpu_num.get_value(),
            min_memory_size = None if x.min_memory_size is None else x.min_memory_size.get_value(),
            max_memory_size = None if x.max_memory_size is None else x.max_memory_size.get_value(),
            min_gpu_num = None if x.min_gpu_num is None else x.min_gpu_num.get_value(),
            max_gpu_num = None if x.max_gpu_num is None else x.max_gpu_num.get_value(),
            min_gpu_memory_size = None if x.min_gpu_memory_size is None else x.min_gpu_memory_size.get_value(),
            max_gpu_memory_size = None if x.max_gpu_memory_size is None else x.max_gpu_memory_size.get_value()
        )
condition_assembler=ConditionAssembler()



class DatapipeServerInfoAssembler(Assembler):
    def to_entity(self, dto: DatapipeServerInfoDTO):
        return DatapipeServerInfo(
            id = UStr(dto.id),
            secret = UStr(dto.secret),
            endpoint = UStr(dto.endpoint)
        )
    def to_dto(self, x:DatapipeServerInfo):
        return DatapipeServerInfoDTO(
            id = x.id.get_value(),
            secret = x.secret.get_value(),
            endpoint = x.endpoint.get_value()
        )
datapipe_server_info_assembler=DatapipeServerInfoAssembler()



class DatapipeDataInfoAssembler(Assembler):
    def to_entity(self, dto: DatapipeDataInfoDTO):
        return DatapipeDataInfo(
            bucket = UStr(dto.bucket),
            remote_path = UStr(dto.remote_path),
            local_path = UStr(dto.local_path),
            timeout = UInt(dto.timeout)
        )
    def to_dto(self, x:DatapipeDataInfo):
        return DatapipeDataInfoDTO(
            bucket = x.bucket.get_value(),
            remote_path = x.remote_path.get_value(),
            local_path = x.local_path.get_value(),
            timeout = x.timeout.get_value()
        )
datapipe_data_info_assembler=DatapipeDataInfoAssembler()



class ClusterConfigDataAssembler(Assembler):
    def to_entity(self, dto: ClusterConfigDataDTO):
        return ClusterConfigData(
            data_server = datapipe_server_info_assembler.to_entity(dto.data_server),
            data = [datapipe_data_info_assembler.to_entity(m) for m in dto.data]
        )
    def to_dto(self, x:ClusterConfigData):
        return ClusterConfigDataDTO(
            data_server = datapipe_server_info_assembler.to_dto(x.data_server),
            data = [datapipe_data_info_assembler.to_dto(m) for m in x.data]
        )
cluster_config_data_assembler=ClusterConfigDataAssembler()



class ClusterConfigAssembler(Assembler):
    def to_entity(self, dto: ClusterConfigDTO):
        return ClusterConfig(
            cluster_name = UStr(dto.cluster_name),
            region_id = UStr(dto.region_id),
            config_data = None if dto.config_data is None else cluster_config_data_assembler.to_entity(dto.config_data),
            entry_point = None if dto.entry_point is None else [UStr(m) for m in dto.entry_point],
            timeout = UInt(dto.timeout)
        )
    def to_dto(self, x:ClusterConfig):
        return ClusterConfigDTO(
            cluster_name = x.cluster_name.get_value(),
            region_id = x.region_id.get_value(),
            config_data = None if x.config_data is None else cluster_config_data_assembler.to_dto(x.config_data),
            entry_point = None if x.entry_point is None else [m.get_value() for m in x.entry_point],
            timeout = x.timeout.get_value()
        )
cluster_config_assembler=ClusterConfigAssembler()



class BootstrapInfoAssembler(Assembler):
    def to_entity(self, dto: BootstrapInfoDTO):
        return BootstrapInfo(
            cluster_config = cluster_config_assembler.to_entity(dto.cluster_config),
            template = UStr(dto.template),
            platform = UStr(dto.platform),
            patch_setting = None if dto.patch_setting is None else UDict(dto.patch_setting)
        )
    def to_dto(self, x:BootstrapInfo):
        return BootstrapInfoDTO(
            cluster_config = cluster_config_assembler.to_dto(x.cluster_config),
            template = x.template.get_value(),
            platform = x.platform.get_value(),
            patch_setting = None if x.patch_setting is None else x.patch_setting.get_value()
        )
bootstrap_info_assembler=BootstrapInfoAssembler()



class RandomTemplateVariablesAssembler(Assembler):
    def to_entity(self, dto: RandomTemplateVariablesDTO):
        return RandomTemplateVariables(
            variables = [UStr(m) for m in dto.variables],
            lengths = None if dto.lengths is None else [UInt(m) for m in dto.lengths]
        )
    def to_dto(self, x:RandomTemplateVariables):
        return RandomTemplateVariablesDTO(
            variables = [m.get_value() for m in x.variables],
            lengths = None if x.lengths is None else [m.get_value() for m in x.lengths]
        )
random_template_variables_assembler=RandomTemplateVariablesAssembler()



class FileTemplateVariablesAssembler(Assembler):
    def to_entity(self, dto: FileTemplateVariablesDTO):
        return FileTemplateVariables(
            variables = None if dto.variables is None else [UStr(m) for m in dto.variables],
            path = UStr(dto.path)
        )
    def to_dto(self, x:FileTemplateVariables):
        return FileTemplateVariablesDTO(
            variables = None if x.variables is None else [m.get_value() for m in x.variables],
            path = x.path.get_value()
        )
file_template_variables_assembler=FileTemplateVariablesAssembler()



class FilesTemplateVariablesAssembler(Assembler):
    def to_entity(self, dto: FilesTemplateVariablesDTO):
        return FilesTemplateVariables(
            variables = [UStr(m) for m in dto.variables],
            paths = [UStr(m) for m in dto.paths]
        )
    def to_dto(self, x:FilesTemplateVariables):
        return FilesTemplateVariablesDTO(
            variables = [m.get_value() for m in x.variables],
            paths = [m.get_value() for m in x.paths]
        )
files_template_variables_assembler=FilesTemplateVariablesAssembler()



class APIGatewayRequestAssembler(Assembler):
    def to_entity(self, dto: APIGatewayRequestDTO):
        return APIGatewayRequest(
            service_name = UStr(dto.service_name),
            method = UStr(dto.method),
            ip = None if dto.ip is None else UStr(dto.ip),
            port = None if dto.port is None else UInt(dto.port),
            route = None if dto.route is None else UStr(dto.route),
            action = None if dto.action is None else UStr(dto.action),
            auth = None if dto.auth is None else UDict(dto.auth),
            data = None if dto.data is None else UDict(dto.data)
        )
    def to_dto(self, x:APIGatewayRequest):
        return APIGatewayRequestDTO(
            service_name = x.service_name.get_value(),
            method = x.method.get_value(),
            ip = None if x.ip is None else x.ip.get_value(),
            port = None if x.port is None else x.port.get_value(),
            route = None if x.route is None else x.route.get_value(),
            action = None if x.action is None else x.action.get_value(),
            auth = None if x.auth is None else x.auth.get_value(),
            data = None if x.data is None else x.data.get_value()
        )
api_gateway_request_assembler=APIGatewayRequestAssembler()



class APIGatewayBlacklistItemAssembler(Assembler):
    def to_entity(self, dto: APIGatewayBlacklistItemDTO):
        return APIGatewayBlacklistItem(
            ip = UStr(dto.ip),
            creation_time = UStr(dto.creation_time),
            limit_time = UInt(dto.limit_time),
            limit_reason = UStr(dto.limit_reason)
        )
    def to_dto(self, x:APIGatewayBlacklistItem):
        return APIGatewayBlacklistItemDTO(
            ip = x.ip.get_value(),
            creation_time = x.creation_time.get_value(),
            limit_time = x.limit_time.get_value(),
            limit_reason = x.limit_reason.get_value()
        )
api_gateway_blacklist_item_assembler=APIGatewayBlacklistItemAssembler()



class TaskRequestAssembler(Assembler):
    def to_entity(self, dto: TaskRequestDTO):
        return TaskRequest(
            task_name = UStr(dto.task_name),
            region_id = UStr(dto.region_id),
            condition = condition_assembler.to_entity(dto.condition),
            git_url = None if dto.git_url is None else UStr(dto.git_url),
            git_branch = None if dto.git_branch is None else UStr(dto.git_branch),
            task_type = None if dto.task_type is None else UStr(dto.task_type),
            task_template = None if dto.task_template is None else UStr(dto.task_template),
            task_env = None if dto.task_env is None else UDict(dto.task_env),
            task_command = None if dto.task_command is None else [UStr(m) for m in dto.task_command],
            task_arg = None if dto.task_arg is None else [UStr(m) for m in dto.task_arg],
            task_working_dir = None if dto.task_working_dir is None else UStr(dto.task_working_dir),
            task_image = None if dto.task_image is None else UStr(dto.task_image),
            task_start_time = None if dto.task_start_time is None else UStr(dto.task_start_time),
            priority = UInt(dto.priority),
            amount = UInt(dto.amount),
            duration = None if dto.duration is None else UInt(dto.duration),
            disk_size = None if dto.disk_size is None else UInt(dto.disk_size),
            end_style = UStr(dto.end_style),
            restart_policy = UStr(dto.restart_policy),
            timeout = UInt(dto.timeout),
            cluster_name = None if dto.cluster_name is None else UStr(dto.cluster_name)
        )
    def to_dto(self, x:TaskRequest):
        return TaskRequestDTO(
            task_name = x.task_name.get_value(),
            region_id = x.region_id.get_value(),
            condition = condition_assembler.to_dto(x.condition),
            git_url = None if x.git_url is None else x.git_url.get_value(),
            git_branch = None if x.git_branch is None else x.git_branch.get_value(),
            task_type = None if x.task_type is None else x.task_type.get_value(),
            task_template = None if x.task_template is None else x.task_template.get_value(),
            task_env = None if x.task_env is None else x.task_env.get_value(),
            task_command = None if x.task_command is None else [m.get_value() for m in x.task_command],
            task_arg = None if x.task_arg is None else [m.get_value() for m in x.task_arg],
            task_working_dir = None if x.task_working_dir is None else x.task_working_dir.get_value(),
            task_image = None if x.task_image is None else x.task_image.get_value(),
            task_start_time = None if x.task_start_time is None else x.task_start_time.get_value(),
            priority = x.priority.get_value(),
            amount = x.amount.get_value(),
            duration = None if x.duration is None else x.duration.get_value(),
            disk_size = None if x.disk_size is None else x.disk_size.get_value(),
            end_style = x.end_style.get_value(),
            restart_policy = x.restart_policy.get_value(),
            timeout = x.timeout.get_value(),
            cluster_name = None if x.cluster_name is None else x.cluster_name.get_value()
        )
task_request_assembler=TaskRequestAssembler()



class TaskDeleteRequestAssembler(Assembler):
    def to_entity(self, dto: TaskDeleteRequestDTO):
        return TaskDeleteRequest(
            task_name = None if dto.task_name is None else UStr(dto.task_name),
            task_id = None if dto.task_id is None else UStr(dto.task_id),
            delay = None if dto.delay is None else UInt(dto.delay)
        )
    def to_dto(self, x:TaskDeleteRequest):
        return TaskDeleteRequestDTO(
            task_name = None if x.task_name is None else x.task_name.get_value(),
            task_id = None if x.task_id is None else x.task_id.get_value(),
            delay = None if x.delay is None else x.delay.get_value()
        )
task_delete_request_assembler=TaskDeleteRequestAssembler()



class TaskDetailAssembler(Assembler):
    def to_entity(self, dto: TaskDetailDTO):
        return TaskDetail(
            detail_id = UStr(dto.detail_id),
            ip = UStr(dto.ip),
            node_status = None if dto.node_status is None else Status(dto.node_status),
            job_status = None if dto.job_status is None else Status(dto.job_status),
            exception = None if dto.exception is None else UStr(dto.exception)
        )
    def to_dto(self, x:TaskDetail):
        return TaskDetailDTO(
            detail_id = x.detail_id.get_value(),
            ip = x.ip.get_value(),
            node_status = None if x.node_status is None else x.node_status.get_value(),
            job_status = None if x.job_status is None else x.job_status.get_value(),
            exception = None if x.exception is None else x.exception.get_value()
        )
task_detail_assembler=TaskDetailAssembler()



class TaskItemAssembler(Assembler):
    def to_entity(self, dto: TaskItemDTO):
        return TaskItem(
            request = None if dto.request is None else task_request_assembler.to_entity(dto.request),
            delete_request = None if dto.delete_request is None else task_delete_request_assembler.to_entity(dto.delete_request),
            task_id = UStr(dto.task_id),
            creation_time = UDate(dto.creation_time),
            status = Status(dto.status),
            details = None if dto.details is None else [task_detail_assembler.to_entity(m) for m in dto.details],
            entry_time = None if dto.entry_time is None else UDate(dto.entry_time),
            exit_time = None if dto.exit_time is None else UDate(dto.exit_time),
            exception = None if dto.exception is None else UStr(dto.exception)
        )
    def to_dto(self, x:TaskItem):
        return TaskItemDTO(
            request = None if x.request is None else task_request_assembler.to_dto(x.request),
            delete_request = None if x.delete_request is None else task_delete_request_assembler.to_dto(x.delete_request),
            task_id = x.task_id.get_value(),
            creation_time = x.creation_time.get_value(),
            status = x.status.get_value(),
            details = None if x.details is None else [task_detail_assembler.to_dto(m) for m in x.details],
            entry_time = None if x.entry_time is None else x.entry_time.get_value(),
            exit_time = None if x.exit_time is None else x.exit_time.get_value(),
            exception = None if x.exception is None else x.exception.get_value()
        )
task_item_assembler=TaskItemAssembler()



class NodeInventoryAssembler(Assembler):
    def to_entity(self, dto: NodeInventoryDTO):
        return NodeInventory(
            node_type = UStr(dto.node_type),
            amount = UInt(dto.amount)
        )
    def to_dto(self, x:NodeInventory):
        return NodeInventoryDTO(
            node_type = x.node_type.get_value(),
            amount = x.amount.get_value()
        )
node_inventory_assembler=NodeInventoryAssembler()



class DNSInventoryAssembler(Assembler):
    def to_entity(self, dto: DNSInventoryDTO):
        return DNSInventory(
            domain = UStr(dto.domain),
            subdomain = UStr(dto.subdomain),
            node_type = None if dto.node_type is None else K3SNodeType(dto.node_type),
            pod_name = None if dto.pod_name is None else UStr(dto.pod_name),
            namespace_name = None if dto.namespace_name is None else UStr(dto.namespace_name)
        )
    def to_dto(self, x:DNSInventory):
        return DNSInventoryDTO(
            domain = x.domain.get_value(),
            subdomain = x.subdomain.get_value(),
            node_type = None if x.node_type is None else x.node_type.get_value(),
            pod_name = None if x.pod_name is None else x.pod_name.get_value(),
            namespace_name = None if x.namespace_name is None else x.namespace_name.get_value()
        )
dns_inventory_assembler=DNSInventoryAssembler()



class RecoverSettingAssembler(Assembler):
    def to_entity(self, dto: RecoverSettingDTO):
        return RecoverSetting(
            node_inventory = None if dto.node_inventory is None else [node_inventory_assembler.to_entity(m) for m in dto.node_inventory],
            dns_inventory = None if dto.dns_inventory is None else [dns_inventory_assembler.to_entity(m) for m in dto.dns_inventory]
        )
    def to_dto(self, x:RecoverSetting):
        return RecoverSettingDTO(
            node_inventory = None if x.node_inventory is None else [node_inventory_assembler.to_dto(m) for m in x.node_inventory],
            dns_inventory = None if x.dns_inventory is None else [dns_inventory_assembler.to_dto(m) for m in x.dns_inventory]
        )
recover_setting_assembler=RecoverSettingAssembler()



class SearchRequestAssembler(Assembler):
    def to_entity(self, dto: SearchRequestDTO):
        return SearchRequest(
            keyword = UStr(dto.keyword),
            limit = UInt(dto.limit),
            request_id = None if dto.request_id is None else UStr(dto.request_id),
            others = None if dto.others is None else UDict(dto.others)
        )
    def to_dto(self, x:SearchRequest):
        return SearchRequestDTO(
            keyword = x.keyword.get_value(),
            limit = x.limit.get_value(),
            request_id = None if x.request_id is None else x.request_id.get_value(),
            others = None if x.others is None else x.others.get_value()
        )
search_request_assembler=SearchRequestAssembler()



class SearchResponseAssembler(Assembler):
    def to_entity(self, dto: SearchResponseDTO):
        return SearchResponse(
            status = Status(dto.status),
            exception = None if dto.exception is None else UStr(dto.exception),
            result = None if dto.result is None else UDict(dto.result),
            others = None if dto.others is None else UDict(dto.others)
        )
    def to_dto(self, x:SearchResponse):
        return SearchResponseDTO(
            status = x.status.get_value(),
            exception = None if x.exception is None else x.exception.get_value(),
            result = None if x.result is None else x.result.get_value(),
            others = None if x.others is None else x.others.get_value()
        )
search_response_assembler=SearchResponseAssembler()



class SearchItemAssembler(Assembler):
    def to_entity(self, dto: SearchItemDTO):
        return SearchItem(
            item_id = UStr(dto.item_id),
            status = Status(dto.status),
            exception = None if dto.exception is None else UStr(dto.exception),
            request = None if dto.request is None else search_request_assembler.to_entity(dto.request),
            response = None if dto.response is None else search_response_assembler.to_entity(dto.response),
            entry_time = None if dto.entry_time is None else UDate(dto.entry_time),
            exit_time = None if dto.exit_time is None else UDate(dto.exit_time),
            create_time = None if dto.create_time is None else UDate(dto.create_time)
        )
    def to_dto(self, x:SearchItem):
        return SearchItemDTO(
            item_id = x.item_id.get_value(),
            status = x.status.get_value(),
            exception = None if x.exception is None else x.exception.get_value(),
            request = None if x.request is None else search_request_assembler.to_dto(x.request),
            response = None if x.response is None else search_response_assembler.to_dto(x.response),
            entry_time = None if x.entry_time is None else x.entry_time.get_value(),
            exit_time = None if x.exit_time is None else x.exit_time.get_value(),
            create_time = None if x.create_time is None else x.create_time.get_value()
        )
search_item_assembler=SearchItemAssembler()
