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

# %% auto 0
__all__ = ['DomoCard', 'Card_DownloadSourceCode']

# %% ../../nbs/classes/50_DomoCard.ipynb 2
from domolibrary.client.DomoEntity import DomoEntity, DomoEntity_w_Lineage
import domolibrary.client.DomoAuth as dmda
import domolibrary.client.DomoError as dmde

import domolibrary.routes.card as card_routes

import domolibrary.classes.DomoLineage as dmdl


import domolibrary.utils.DictDot as util_dd
import domolibrary.utils.chunk_execution as dmce
import domolibrary.utils.convert as dmut
import domolibrary.utils.files as dmfi

from dataclasses import dataclass, field
from typing import List, Any
from copy import deepcopy
import json


import httpx
from nbdev.showdoc import patch_to

# %% ../../nbs/classes/50_DomoCard.ipynb 5
@dataclass
class DomoCard(DomoEntity_w_Lineage):
    auth: dmda.DomoAuth = field(repr=False)
    id: str
    Lineage: "dmdl.DomoLineage" = field(repr=False)

    title: str = None
    description: str = None
    type: str = None
    urn: str = None
    chart_type: str = None
    dataset_id: str = None

    datastore_id: str = None

    domo_collections: List[Any] = None
    domo_source_code: Any = None

    certification: dict = None
    owners: List[any] = None

    datasets: List[Any] = field(repr=False, default=None)

    def __post_init__(self):
        # self.Definition = CardDefinition(self)
        self.Lineage = dmdl.DomoLineage._from_parent(auth=self.auth, parent=self)

    def display_url(self) -> str:
        return f"https://{self.auth.domo_instance}.domo.com/kpis/details/{self.id}"

    @classmethod
    async def _from_json(cls, card_obj, auth: dmda.DomoAuth):
        import domolibrary.classes.DomoUser as dmdu
        import domolibrary.classes.DomoGroup as dmgr

        dd = card_obj
        if isinstance(card_obj, dict):
            dd = util_dd.DictDot(card_obj)

        card = cls(
            auth=auth,
            id=dd.id,
            raw=card_obj,
            title=dd.title,
            description=dd.description,
            type=dd.type,
            urn=dd.urn,
            certification=dd.certification,
            chart_type=dd.metadata and dd.metadata.chartType,
            dataset_id=dd.datasources[0].dataSourceId if dd.datasources else None,
            Lineage=None,
        )

        tasks = []
        for user in dd.owners:
            if user.type == "USER":
                tasks.append(dmdu.DomoUser.get_by_id(user_id=user.id, auth=auth))
            if user.type == "GROUP":
                tasks.append(dmgr.DomoGroup.get_by_id(group_id=user.id, auth=auth))

        card.owners = await dmce.gather_with_concurrency(n=60, *tasks)

        if card_obj.get("domoapp", {}).get("id"):
            card.datastore_id = card_obj["domoapp"]["id"]

        return card

    @classmethod
    async def get_by_id(
        cls,
        card_id: str,
        auth: dmda.DomoAuth,
        optional_parts: str = "certification,datasources,drillPath,owners,properties,domoapp",
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
    ):

        res = await card_routes.get_card_metadata(
            auth=auth,
            card_id=card_id,
            optional_parts=optional_parts,
            debug_api=debug_api,
            session=session,
            parent_class=cls.__name__,
        )

        if return_raw:
            return res

        domo_card = await cls._from_json(res.response, auth)

        return domo_card

    async def _get_entity_by_id(cls, entity_id: str, auth: dmda.DomoAuth, **kwargs):
        return await cls.get_by_id(card_id=entity_id, auth=auth, **kwargs)

# %% ../../nbs/classes/50_DomoCard.ipynb 7
@patch_to(DomoCard)
async def get_datasets(
    self,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    return_raw: bool = False,
):

    res = await card_routes.get_card_metadata(
        auth=self.auth,
        card_id=self.id,
        optional_parts="datasources",
        debug_api=debug_api,
        session=session,
        parent_class=self.__class__.__name__,
    )

    res.response = res.response["datasources"]

    if return_raw:
        return res

    import domolibrary.classes.DomoDataset as dmds

    self.datasets = await dmce.gather_with_concurrency(
        *[
            dmds.DomoDataset.get_by_id(dataset_id=obj["dataSourceId"], auth=self.auth)
            for obj in res.response
        ],
        n=10
    )

    return self.datasets

# %% ../../nbs/classes/50_DomoCard.ipynb 9
@patch_to(DomoCard)
async def share(
    self: DomoCard,
    auth: dmda.DomoAuth = None,
    domo_users: list = None,  # DomoUsers to share card with,
    domo_groups: list = None,  # DomoGroups to share card with
    message: str = None,  # message for automated email
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
):
    import domolibrary.routes.datacenter as datacenter_routes

    if domo_groups:
        domo_groups = domo_groups if isinstance(domo_groups, list) else [domo_groups]
    if domo_users:
        domo_users = domo_users if isinstance(domo_users, list) else [domo_users]

    res = await datacenter_routes.share_resource(
        auth=auth or self.auth,
        resource_ids=[self.id],
        resource_type=datacenter_routes.ShareResource_Enum.CARD,
        group_ids=[group.id for group in domo_groups] if domo_groups else None,
        user_ids=[user.id for user in domo_users] if domo_users else None,
        message=message,
        debug_api=debug_api,
        session=session,
    )

    return res

# %% ../../nbs/classes/50_DomoCard.ipynb 12
class Card_DownloadSourceCode(dmde.DomoError):
    def __init__(self, cls, auth, message):
        super().__init__(cls=cls, auth=auth, message=message)


@patch_to(DomoCard)
async def get_collections(
    self, debug_api: bool = False, return_raw: bool = False, debug_num_stacks_to_drop=2
):
    import domolibrary.classes.DomoAppDb as dmdb

    domo_collections = await dmdb.AppDbCollections.get_collections(
        datastore_id=self.datastore_id,
        auth=self.auth,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        return_raw=return_raw,
    )

    if return_raw:
        return domo_collections

    self.domo_collections = await dmce.gather_with_concurrency(
        *[
            dmdb.AppDbCollection.get_by_id(
                collection_id=domo_collection.id, auth=self.auth, debug_api=debug_api
            )
            for domo_collection in domo_collections
        ],
        n=60,
    )

    return self.domo_collections


@patch_to(DomoCard)
async def get_source_code(self, debug_api: bool = False, try_auto_share: bool = False):

    await self.get_collections(debug_api=debug_api)

    collection_name = "ddx_app_client_code"
    code_collection = next(
        (
            domo_collection
            for domo_collection in self.domo_collections
            if domo_collection.name == collection_name
        ),
        None,
    )

    if not code_collection:
        raise Card_DownloadSourceCode(
            cls=deepcopy(self),
            auth=self.auth,
            message=f"collection - {collection_name} not found for {self.title} - {self.id}",
        )

    documents = await code_collection.query_documents(
        debug_api=debug_api, try_auto_share=try_auto_share
    )

    if not documents:
        raise Card_DownloadSourceCode(
            cls=deepcopy(self),
            auth=self.auth,
            message=f"collection - {collection_name} - {code_collection.id} - unable to retrieve documents for {self.title} - {self.id}",
        )

    self.domo_source_code = documents[0]

    return self.domo_source_code

# %% ../../nbs/classes/50_DomoCard.ipynb 14
@patch_to(DomoCard)
async def download_source_code(
    self,
    download_folder="./EXPORT/",
    file_name=None,
    debug_api: bool = False,
    try_auto_share: bool = False,
):
    doc = await self.get_source_code(debug_api=debug_api, try_auto_share=try_auto_share)

    if file_name:
        download_path = os.path.join(
            download_folder, dmut.change_suffix(file_name, new_extension=".json")
        )
        dmfi.upsert_folder(download_path)

        with open(download_path, "w+", encoding="utf-8") as f:
            f.write(json.dumps(doc.content))
            return doc

    ddx_type = next(iter(doc.content))

    for key, value in doc.content[ddx_type].items():
        if key == "js":
            file_name = "app.js"
        elif key == "html":
            file_name = "index.html"
        elif key == "css":
            file_name = "styles.css"
        else:
            file_name = f"{key}.txt"

        download_path = os.path.join(
            download_folder, f"{ddx_type}/{self.id}/{file_name}"
        )
        dmfi.upsert_folder(download_path)

        with open(download_path, "w+", encoding="utf-8") as f:
            f.write(value)

    return doc
