# 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 create_contact_group(dbcon: DBConnection, name: str, active: bool) -> str:
    """Add a contact group to the database."""
    q = """insert into contact_groups (name, active) values (%s, %s)"""
    q_args = (name, active)
    contact_group_id = await dbcon.operation(q, q_args)
    return contact_group_id


async def update_contact_group(dbcon: DBConnection, contact_group_id: int, data: Dict[str, str]) -> None:
    """Update a contact groups information in the database.

    Data is a dict with name/active values that will be updated.
    """

    async def _run(cur: Cursor) -> None:
        for key, value in data.items():
            if key not in ['name', 'active']:
                raise errors.IrisettError('invalid contact key %s' % key)
            q = """update contact_groups set %s=%%s where id=%%s""" % key
            q_args = (value, contact_group_id)
            await cur.execute(q, q_args)

    if not await contact_group_exists(dbcon, contact_group_id):
        raise errors.InvalidArguments('contact group does not exist')
    await dbcon.transact(_run)


async def delete_contact_group(dbcon: DBConnection, contact_group_id: int) -> None:
    """Remove a contact group from the database."""

# 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 create_contact_group(dbcon: DBConnection, name: str, active: bool) -> str:
    """Add a contact group to the database."""
    q = """insert into contact_groups (name, active) values (%s, %s)"""
    q_args = (name, active)
    contact_group_id = await dbcon.operation(q, q_args)
    return contact_group_id


async def update_contact_group(dbcon: DBConnection, contact_group_id: int, data: Dict[str, str]) -> None:
    """Update a contact groups information in the database.

    Data is a dict with name/active values that will be updated.
    """

    async def _run(cur: Cursor) -> None:
        for key, value in data.items():
            if key not in ['name', 'active']:
                raise errors.IrisettError('invalid contact key %s' % key)
            q = """update contact_groups set %s=%%s where id=%%s""" % key
            q_args = (value, contact_group_id)
            await cur.execute(q, q_args)

    if not await contact_group_exists(dbcon, contact_group_id):
        raise errors.InvalidArguments('contact group does not exist')
    await dbcon.transact(_run)


async def delete_contact_group(dbcon: DBConnection, contact_group_id: int) -> None:
    """Remove a contact group from the database."""

    if not await contact_group_exists(dbcon, contact_group_id):