# 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 dataclasses import dataclass, field
from typing import List, Any
from copy import deepcopy
import json


import httpx
from nbdev.showdoc import patch_to

import domolibrary.client.DomoError as de

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

import domolibrary.routes.card as card_routes

import domolibrary.client.DomoAuth as dmda

# %% ../../nbs/classes/50_DomoCard.ipynb 5
@dataclass
class DomoCard:
    id: str
    auth: dmda.DomoAuth = 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

    def __post_init__(self):
        # self.Definition = CardDefinition(self)
        pass

    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 dmu
        import domolibrary.classes.DomoGroup as dmg

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

        card = cls(
            auth=auth,
            id=dd.id,
            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,
        )

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

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

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

        return card

# %% ../../nbs/classes/50_DomoCard.ipynb 6
@patch_to(DomoCard, cls_method=True)
async def get_by_id(
    cls: DomoCard,
    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

# %% ../../nbs/classes/50_DomoCard.ipynb 8
@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 11
class Card_DownloadSourceCode(de.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 ce.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 13
@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
