# Path: irisett/sql.py
# class DBConnection:
#     def __init__(self, host: str, user: str, passwd: str, dbname: str, loop: asyncio.AbstractEventLoop=None) -> None:
#     async def initialize(self, *, only_init_tables: bool=False):
#     async def close(self) -> None:
#     async def _create_db(self) -> None:
#     async def _init_db(self, only_init_tables: bool) -> None:
#     async def _check_db_exists(self) -> bool:
#     async def _check_db_initialized(self) -> bool:
#     async def _upgrade_db(self) -> None:
#     async def _get_db_version(self) -> int:
#     async def _set_db_version(self, version: int):
#     async def fetch_all(self, query: str, args: Optional[Iterable]=None) -> List:
#     async def fetch_row(self, query: str, args: Optional[Iterable]=None) -> List:
#     async def fetch_single(self, query: str, args: Optional[Iterable]=None) -> Any:
#     async def count_rows(self, query: str, args: Optional[Iterable]=None) -> float:
#     async def operation(self, query: str, args: Optional[Iterable]=None) -> Any:
#     async def transact(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
# 
# Path: irisett/errors.py
# class IrisettError(Exception):
# class InvalidArguments(IrisettError):
#     def __str__(self) -> str:
# 
# Path: irisett/object_models.py
# def insert_values(object: Any) -> Tuple:
# def list_asdict(in_list: Iterable[Any]) -> List[Any]:
# def insert_filter(attribute: Any, value: Any) -> bool:
# class Contact:
# class ContactGroup:
# class ActiveMonitor:
# class ActiveMonitorArg:
# class ActiveMonitorAlert:
# class ActiveMonitorDef:
# class ActiveMonitorDefArg:
# class ObjectMetadata:
# class ObjectBindata:
# class MonitorGroup:
# 
# Path: irisett/object_exists.py
# async def contact_exists(dbcon: DBConnection, contact_id: int) -> bool:
#     """Check if a contact id exists."""
#     q = """select count(id) from contacts where id=%s"""
#     return await _object_exists(dbcon, q, (contact_id,))
# 
# async def active_monitor_exists(dbcon: DBConnection, active_monitor_id: int) -> bool:
#     """Check if a contact id exists."""
#     q = """select count(id) from active_monitors where id=%s"""
#     return await _object_exists(dbcon, q, (active_monitor_id,))
# 
# async def contact_group_exists(dbcon: DBConnection, contact_group_id: int) -> bool:
#     """Check if a contact group id exists."""
#     q = """select count(id) from contact_groups where id=%s"""
#     return await _object_exists(dbcon, q, (contact_group_id,))


from typing import Dict, Iterable, Optional, Any, Set
from irisett.sql import DBConnection, Cursor
from irisett import (
    errors,
    object_models,
)
from irisett.object_exists import (
    contact_exists,
    active_monitor_exists,
    contact_group_exists,
)
async def get_contact_dict_for_active_monitor(dbcon: DBConnection, monitor_id: int) -> Dict[str, set]:
    """Get all contact addresses/numbers for a specific active monitor.

    Return: Dict[str, Set(str)] for 'email' and 'phone'.
    """
    ret = {
        'email': set(),
        'phone': set(),
    }  # type: Dict[str, set]

    contacts = await get_all_contacts_for_active_monitor(dbcon, monitor_id)
    for contact in contacts:
        if contact.email:
            ret['email'].add(contact.email)
        if contact.phone:
            ret['phone'].add(contact.phone)
    return ret


async def add_contact_to_active_monitor(dbcon: DBConnection, contact_id: int, monitor_id: int) -> None:
    """Connect a contact and an active monitor."""
    if not await active_monitor_exists(dbcon, monitor_id):
        raise errors.InvalidArguments('monitor does not exist')
    if not await contact_exists(dbcon, contact_id):
        raise errors.InvalidArguments('contact does not exist')
    q = """replace into active_monitor_contacts (active_monitor_id, contact_id) values (%s, %s)"""
    q_args = (monitor_id, contact_id)
    await dbcon.operation(q, q_args)



# Path: irisett/sql.py
# class DBConnection:
#     def __init__(self, host: str, user: str, passwd: str, dbname: str, loop: asyncio.AbstractEventLoop=None) -> None:
#     async def initialize(self, *, only_init_tables: bool=False):
#     async def close(self) -> None:
#     async def _create_db(self) -> None:
#     async def _init_db(self, only_init_tables: bool) -> None:
#     async def _check_db_exists(self) -> bool:
#     async def _check_db_initialized(self) -> bool:
#     async def _upgrade_db(self) -> None:
#     async def _get_db_version(self) -> int:
#     async def _set_db_version(self, version: int):
#     async def fetch_all(self, query: str, args: Optional[Iterable]=None) -> List:
#     async def fetch_row(self, query: str, args: Optional[Iterable]=None) -> List:
#     async def fetch_single(self, query: str, args: Optional[Iterable]=None) -> Any:
#     async def count_rows(self, query: str, args: Optional[Iterable]=None) -> float:
#     async def operation(self, query: str, args: Optional[Iterable]=None) -> Any:
#     async def transact(self, func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
# 
# Path: irisett/errors.py
# class IrisettError(Exception):
# class InvalidArguments(IrisettError):
#     def __str__(self) -> str:
# 
# Path: irisett/object_models.py
# def insert_values(object: Any) -> Tuple:
# def list_asdict(in_list: Iterable[Any]) -> List[Any]:
# def insert_filter(attribute: Any, value: Any) -> bool:
# class Contact:
# class ContactGroup:
# class ActiveMonitor:
# class ActiveMonitorArg:
# class ActiveMonitorAlert:
# class ActiveMonitorDef:
# class ActiveMonitorDefArg:
# class ObjectMetadata:
# class ObjectBindata:
# class MonitorGroup:
# 
# Path: irisett/object_exists.py
# async def contact_exists(dbcon: DBConnection, contact_id: int) -> bool:
#     """Check if a contact id exists."""
#     q = """select count(id) from contacts where id=%s"""
#     return await _object_exists(dbcon, q, (contact_id,))
# 
# async def active_monitor_exists(dbcon: DBConnection, active_monitor_id: int) -> bool:
#     """Check if a contact id exists."""
#     q = """select count(id) from active_monitors where id=%s"""
#     return await _object_exists(dbcon, q, (active_monitor_id,))
# 
# async def contact_group_exists(dbcon: DBConnection, contact_group_id: int) -> bool:
#     """Check if a contact group id exists."""
#     q = """select count(id) from contact_groups where id=%s"""
#     return await _object_exists(dbcon, q, (contact_group_id,))


# Path: irisett/contact.py
from typing import Dict, Iterable, Optional, Any, Set
from irisett.sql import DBConnection, Cursor
from irisett import (
    errors,
    object_models,
)
from irisett.object_exists import (
    contact_exists,
    active_monitor_exists,
    contact_group_exists,
)

async def get_contact_dict_for_active_monitor(dbcon: DBConnection, monitor_id: int) -> Dict[str, set]:
    """Get all contact addresses/numbers for a specific active monitor.

    Return: Dict[str, Set(str)] for 'email' and 'phone'.
    """
    ret = {
        'email': set(),
        'phone': set(),
    }  # type: Dict[str, set]

    contacts = await get_all_contacts_for_active_monitor(dbcon, monitor_id)
    for contact in contacts:
        if contact.email:
            ret['email'].add(contact.email)
        if contact.phone:
            ret['phone'].add(contact.phone)
    return ret


async def add_contact_to_active_monitor(dbcon: DBConnection, contact_id: int, monitor_id: int) -> None:
    """Connect a contact and an active monitor."""
    if not await active_monitor_exists(dbcon, monitor_id):
        raise errors.InvalidArguments('monitor does not exist')
    if not await contact_exists(dbcon, contact_id):
        raise errors.InvalidArguments('contact does not exist')
    q = """replace into active_monitor_contacts (active_monitor_id, contact_id) values (%s, %s)"""
    q_args = (monitor_id, contact_id)
    await dbcon.operation(q, q_args)



async def delete_contact_from_active_monitor(dbcon: DBConnection, contact_id: int, monitor_id: int) -> None: