# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/classes/CodeEngine.ipynb.

# %% auto 0
__all__ = ['ExportExtension', 'DomoCodeEngine_ConfigError', 'DomoCodeEngine_PackageVersion', 'DomoCodeEngine_Package']

# %% ../../nbs/classes/CodeEngine.ipynb 2
# from domolibrary.routes.codeengine import extract_functions
from .CodeEngineManifest import CodeEngineManifest, CodeEngineManifest_Function, CodeEngineManifest_Argument, CodeEngine_Argument, PythonTypeToSchemaType


# %% ../../nbs/classes/CodeEngine.ipynb 3
import os

from dataclasses import dataclass, field
from enum import Enum
from typing import List, Callable
import datetime as dt

from io import open
import httpx

from nbdev.showdoc import patch_to

import domolibrary.client.DomoAuth as dmda
import domolibrary.client.DomoEntity as dmee    

import domolibrary.routes.codeengine as codeengine_routes
import domolibrary.client.DomoError as dmde
import domolibrary.utils.files as dmuf
from domolibrary.utils.convert import convert_string_to_datetime
import domolibrary.classes.DomoUser as dmdu




# %% ../../nbs/classes/CodeEngine.ipynb 7
class ExportExtension(Enum):
    JAVASCRIPT = "js"
    PYTHON = "py"
    
class DomoCodeEngine_ConfigError(dmde.ClassError):
    def __init__(
        self,
        cls_instance,
        package_id,
        version=None,
        message=None,
        ):
        super().__init__(
            cls_instance=cls_instance,
            entity_id=package_id,
            message=f"verion {version} | {message}" if version else message,
        )
    

# %% ../../nbs/classes/CodeEngine.ipynb 9
@dataclass
class DomoCodeEngine_PackageVersion:
    auth: dmda.DomoAuth = field(repr=False)
    package_id: str
    version: str
    language: str
    description: str
    createdby_id: int
    released_dt: dt.datetime
    configuration: dict

    createdby: dmdu.DomoUser = None
    accounts_mapping: List[int] = None
    ml_model: List[str] = None

    code: str = field(repr=False, default=None)
    # functions_ls: List[CodeEngineManifest_Function] = field(repr=False, default=None)
    functions: dict = None

    Manifest : CodeEngineManifest = field(default=None)

    def _set_configuration(self, configuration=None):
        if configuration:
            self.configuration = configuration

        if not self.configuration:
            raise DomoCodeEngine_ConfigError(
                cls_instance=self,
                package_id=self.package_id,
                version=self.version,
                message="unable to set configuration",
            )

        self.accounts_mapping = self.configuration["accountsMapping"]
        self.ml_model = self.configuration["mlModel"]

        return self

    # def set_functions(
    #     self,
    #     code: str = None,
    #     functions: List[dict] = None,
    #     language: str = None,
    #     # function_parser_fn: Callable = None,  # must receive code string, function_ls, language
    # ):
    #     self.code = code or self.code

    #     self.functions_ls = functions or self.functions_ls

    #     self.language = language or self.language

    #     if not self.code or not self.configuration or not self.language:
    #         raise DomoCodeEngine_ConfigError(
    #             cls_instance=self,
    #             package_id=self.package_id,
    #             version=self.version,
    #             message="API did not return code, configuration or language -- unable to set functions",
    #         )
        # try:
            # function_parser_fn = function_parser_fn or extract_functions
            
            # functions_ls = function_parser_fn(
            #     code=self.code, 
            #     function_ls=self.functions_ls, 
            #     language=self.language
            # )

            # self.functions = [
            #     DomoCodeEngine_Function._from_json(
            #         obj,
            #         is_private= obj.pop("is_private", False),
            #         language=self.language,
            #         package_id=self.package_id,
            #         version=self.version,
            #         code_raw=self.code,
            #     )
            #     for obj in functions_ls
            # ]
            # return functions
        
        # except Exception as e:
        #     print(e)
        #     raise DomoCodeEngine_ConfigError(
        #         package_id=self.package_id,
        #         version=self.version,
        #         message=e,
        #         domo_instance=self.auth.domo_instance,
        #     )

    @classmethod
    def _from_json(
        cls,
        obj: dict,
        package_id,
        auth: dmda.DomoAuth,
        language: str,
        is_supress_error: bool = True,
    ):

        language = (language or obj.get("language", None)).upper()

        domo_version = cls(
            auth=auth,
            package_id=package_id,
            language=language,
            version=obj["version"],
            code=obj.get("code"),
            description=obj.get("description", None),
            createdby_id=obj["createdBy"],
            released_dt=convert_string_to_datetime(obj.get("releasedOn")),
            configuration=obj["configuration"],
            # functions_ls=obj["functions"],
            Manifest = CodeEngineManifest.from_api(obj = obj) if language == "PYTHON" else None 
        )

        # try:
        domo_version._set_configuration()

        # except DomoCodeEngine_ConfigError as e:
        #     print(e)
        #     if not is_supress_error:
        #         raise e from e

        # try:
        #     domo_version.set_functions()
        # except DomoCodeEngine_ConfigError as e:
        #     print(e)
        #     if not is_supress_error:
        #         raise e from e

        return domo_version

    @classmethod
    async def get_by_id_and_version(
        cls,
        package_id,
        version,
        auth: dmda.DomoAuth,
        language: str = None,
        params: dict = None , # {"parts": "functions,code"}
        debug_api: bool = False,
        debug_num_stacks_to_drop=2,
        return_raw: bool = False,
        session: httpx.AsyncClient = None,
    ):
        params = params or {"parts": "functions,code"}

        res = await codeengine_routes.get_codeengine_package_by_id_and_version(
            package_id=package_id,
            version=version,
            auth=auth,
            params = params,
            debug_api=debug_api,
            session=session,
            parent_class=cls.__name__,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )

        if return_raw:
            return res

        return cls._from_json(
            auth=auth, obj=res.response, 
            package_id=package_id, 
            language=language
        )

    def __eq__(self, other):
        if not isinstance(other, DomoCodeEngine_PackageVersion):
            return False

        if self.version != other.version or self.package_id != other.package_id:
            return False

        return True

    async def download_source_code(
        self,
        download_folder: str = "./EXPORT/codeengine",
        file_name: str = None,
        debug_api: bool = False,
        replace_folder : bool = False
        
    ):
        if not self.code:
            self.code = (await self.get_by_id_and_version(
                auth=self.auth,
                package_id=self.package_id,
                version=self.version,
                debug_api=debug_api,
                params = {"parts" : "code"} 
            )).code

        extension = '.txt'
        if self.language == "PYTHON":
            extension = '.py'

        if self.language == "JAVASCRIPT":
            extension = '.js'
            
        file_name = file_name or f'{self.package_id}/{self.version}/functions{extension}'

        file_path = os.path.join(download_folder, file_name)

        if self.Manifest:
            return self.Manifest.download_source_code(
                export_folder=os.path.join(download_folder, file_path), replace_folder=replace_folder)

        dmuf.upsert_file(file_path, content = self.code, replace_folder=replace_folder)



# %% ../../nbs/classes/CodeEngine.ipynb 13
@patch_to(DomoCodeEngine_PackageVersion)
def export(
    self,
    file_name: str = None,
    output_folder: str = "EXPORT/code_engine/",
    debug_prn: bool = False,
):
    output_folder = (
        f"{output_folder}/" if not output_folder.endswith("/") else output_folder
    )

    dmuf.upsert_folder(output_folder)

    file_name = file_name or self.package_id
    file_name = dmuf.change_extension(file_name, ExportExtension[self.language].value)

    file_path = os.path.join(output_folder, file_name)

    if debug_prn:
        print(output_folder, file_name)

    with open(file_path, "w+", newline="\n", encoding="utf-8") as f:
        f.write(self.code)

    return file_path

# %% ../../nbs/classes/CodeEngine.ipynb 15
@dataclass
class DomoCodeEngine_Package:
    auth: dmda.DomoAuth = field(repr=False)
    id: str
    name: str
    description: str
    language: str
    environment: str
    availability: str
    owner_id: int
    created: dt.datetime
    last_modified: dt.datetime
    functions: List

    current_version: str = None
    versions: List[DomoCodeEngine_PackageVersion] = None
    owner: List[dmdu.DomoUser] = None

    def __post_init__(self):
        self._set_current_version()

    def _set_current_version(self):
        if not self.versions:
            return

        versions = [version.version for version in self.versions]
        self.current_version = max(versions)

    @classmethod
    def from_packages_api(cls, obj, auth):
        package_id = obj["id"]
        language = obj["language"]
        versions = [
            DomoCodeEngine_PackageVersion._from_json(
                version, package_id=package_id, language=language, auth=auth
            )
            for version in obj.get("versions")
        ]

        return cls(
            auth=auth,
            id=package_id,
            name=obj["name"],
            description=obj.get("description"),
            language=language,
            environment=obj.get("environment"),
            availability=obj.get("availability"),
            owner_id=obj.get("owner"),
            versions=versions,
            created=convert_string_to_datetime(obj.get("createdOn")),
            last_modified=convert_string_to_datetime(obj.get("updatedOn")),
            functions=obj.get("functions"),
        )

    @classmethod
    async def get_by_id(
        cls,
        auth: dmda.DomoAuth,
        package_id,
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        debug_num_stacks_to_drop=2,
    ):
        res = await codeengine_routes.get_codeengine_package_by_id(
            package_id,
            auth=auth,
            debug_api=debug_api,
            params=None,
            session=session,
            parent_class=cls.__name__,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )
        if return_raw:
            return res

        return cls.from_packages_api(res.response, auth=auth)

    def __eq__(self, other):
        if not isinstance(other, DomoCodeEngine_Package):
            return False

        if self.id != other.id:
            return False

        return True

# %% ../../nbs/classes/CodeEngine.ipynb 17
@patch_to(DomoCodeEngine_Package, cls_method=True)
async def get_current_version_by_id(
    cls,
    auth: dmda.DomoAuth,
    package_id,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    debug_num_stacks_to_drop=2,
):
    domo_package = await cls.get_by_id(
        package_id=package_id,
        auth=auth,
        debug_api=debug_api,
        session=session,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    current_version = domo_package.current_version

    if not domo_package.current_version:
        raise DomoCodeEngine_ConfigError(
            package_id=package_id,
            version=None,
            message="No current version found for the package",
            domo_instance=auth.domo_instance,
        )

    domo_version = await DomoCodeEngine_PackageVersion.get_by_id_and_version(
        package_id=package_id,
        version=current_version,
        auth=auth,
        language=domo_package.language,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        session=session,
    )

    return domo_version
