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

# %% auto 0
__all__ = ['DomoJob_Types', 'DomoApplication']

# %% ../../nbs/classes/50_DomoApplication.ipynb 2
import pandas as pd
from dataclasses import dataclass, field
from typing import Optional, List
from enum import Enum
import httpx

from nbdev.showdoc import patch_to

import domolibrary.routes.application as application_routes
import domolibrary.classes.DomoApplication_Job as dmdj
import domolibrary.utils.convert as cc
import domolibrary.utils.DictDot as util_dd
import domolibrary.client.DomoAuth as dmda

# %% ../../nbs/classes/50_DomoApplication.ipynb 5
class DomoJob_Types(Enum):
    REMOTE_DOMO_STATS = dmdj.DomoJob_RemoteDomoStats
    DATA_WATCHDOG = dmdj.DomoJob_Watchdog

    default = dmdj.DomoJob

    @staticmethod
    def _convert_api_name_to_member_name(api_name):
        return (
            cc.convert_str_to_snake_case(api_name, is_only_alphanumeric=True)
            .upper()
            .replace("TOOLKIT_", "")
        )

    @classmethod
    def get_from_api_name(cls, api_name):
        member_name = cls._convert_api_name_to_member_name(api_name)

        if member_name not in cls.__members__:
            return cls["default"].value

        return cls[member_name].value


DomoJob_Types.get_from_api_name("Toolkit: Remote Domo Stat")

# %% ../../nbs/classes/50_DomoApplication.ipynb 7
@dataclass
class DomoApplication:
    auth: dmda.DomoAuth = field(repr=False)
    id: str
    version: str = None
    name: str = None
    customer_id: str = None
    description: str = None
    execution_class: str = None
    grants: List[str] = None
    jobs: List[dmdj.DomoJob] = field(default=None)
    jobs_schedule: List[dmdj.DomoTrigger_Schedule] = field(default=None, repr=False)

    @classmethod
    def _from_json(cls, obj, auth: dmda.DomoFullAuth = None):
        dd = util_dd.DictDot(obj)

        return cls(
            id=dd.applicationId,
            customer_id=dd.customerId,
            name=dd.name,
            description=dd.description,
            version=dd.version,
            execution_class=dd.executionClass,
            grants=dd.authorities,
            auth=auth,
        )

    def _get_job_class(self):
        return DomoJob_Types.get_from_api_name(self.name)

# %% ../../nbs/classes/50_DomoApplication.ipynb 8
@patch_to(DomoApplication, cls_method=True)
async def get_from_id(
    cls,
    auth: dmda.DomoAuth,
    application_id,
    return_raw: bool = False,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    debug_num_stacks_to_drop=2,
):
    res = await application_routes.get_application_by_id(
        application_id=application_id,
        auth=auth,
        session=session,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
    )

    if return_raw:
        return res

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

# %% ../../nbs/classes/50_DomoApplication.ipynb 10
@patch_to(DomoApplication)
async def get_jobs(
    self,
    debug_api: bool = False,
    session: Optional[httpx.AsyncClient] = None,
    return_raw: bool = False,
):

    res = await application_routes.get_application_jobs(
        auth=self.auth,
        application_id=self.id,
        debug_api=debug_api,
        session=session,
        parent_class=self.__class__.__name__,
    )

    if return_raw:
        return res

    job_cls = self._get_job_class()

    self.jobs = [job_cls._from_json(job, auth=self.auth) for job in res.response]
    return self.jobs

# %% ../../nbs/classes/50_DomoApplication.ipynb 12
@patch_to(DomoApplication)
async def get_schedules(self) -> pd.DataFrame:
    if not self.jobs:
        await self.get_jobs()

    # return self.jobs

    schedules = pd.DataFrame(
        [
            {
                **trigger.schedule.to_obj(),
                "job_name": job.name,
                "job_id": job.id,
                "description": job.description,
                "remote_instance": job.remote_instance,
                "application": self.name,
            }
            for job in self.jobs
            for trigger in job.triggers
        ]
    )

    # return schedules

    self.jobs_schedule = schedules.sort_values(
        ["hour", "minute"], ascending=True
    ).reset_index(drop=True)
    return self.jobs_schedule

# %% ../../nbs/classes/50_DomoApplication.ipynb 14
@patch_to(DomoApplication)
async def find_next_job_schedule(
    self, return_raw: bool = False
) -> dmdj.DomoTrigger_Schedule:

    await self.get_jobs()
    await self.get_schedules()

    df_all_hours = pd.DataFrame(range(0, 23), columns=["hour"])
    df_all_minutes = pd.DataFrame(range(0, 60), columns=["minute"])

    df_all_hours["tmp"] = 1
    df_all_minutes["tmp"] = 1
    df_all = pd.merge(df_all_hours, df_all_minutes, on="tmp").drop(columns=["tmp"])

    # get the number of occurencies of each hour and minutes
    schedules_grouped = (
        self.jobs_schedule.groupby(["hour", "minute"])
        .size()
        .reset_index(name="cnt_schedule")
    )

    # print(schedules_grouped)
    # print(df_all)

    schedules_interpolated = pd.merge(
        df_all, schedules_grouped, how="left", on=["hour", "minute"]
    )

    schedules_interpolated["cnt_schedule"] = schedules_interpolated[
        "cnt_schedule"
    ].fillna(value=0)
    schedules_interpolated.sort_values(
        ["cnt_schedule", "hour", "minute"], ascending=True, inplace=True
    )

    schedules_interpolated.reset_index(drop=True, inplace=True)

    if return_raw:
        return schedules_interpolated

    return dmdj.DomoTrigger_Schedule(
        hour=int(schedules_interpolated.loc[0].get("hour")),
        minute=int(schedules_interpolated.loc[0].get("minute")),
    )
