# This file was generated by mettle.genes.db.GenPy3 [ver 2.1] on Tue Mar 30 15:41:12 2021
#  Target Database = postgresql
#
import asyncio
import copy
import datetime
import uuid
import time
import mettle.lib
import mettle.io
import mettle.db

from bs_loco.db.tables.snap_prov import tSnapProv
from bs_loco.db.tables.snap_prov_key import tSnapProvKey

from .snap_prov_lock_one import dSnapProvLockOne
from .snap_prov_select_one import dSnapProvSelectOne
from .snap_prov_update import dSnapProvUpdate
from .snap_prov_insert import dSnapProvInsert
from .snap_prov_delete_one import dSnapProvDeleteOne

class dSnapProv:

    def __init__(self, dbcon: mettle.db.IConnect):
        """
        Constructor.

        :param dbcon: Mettle database connection object.
        """
        self.rec    = tSnapProv()
        self._dbcon = dbcon

    def __enter__(self):
        """
        DAO enter.
        """
        return self

    def __exit__(self, type, value, traceback):
        """
        DAO exit.
        """
        pass

    def lock_one(self, _lock4update: mettle.db.DBLock, _expected: bool = True) -> bool:
        """
        Lock and select the record.

        :param _lock4update: The db lock object to use.
        :param _expected: If set to false, will not raise if record is not found.
        :return: True if selected, False if not found and _expected is set to False
        """
        _key = tSnapProvKey()

        self.rec._write_key(_key)

        return self.lock_one_by_key(_key, _lock4update, _expected)

    def lock_one_with(self, _rec: tSnapProv, _lock4update: mettle.db.DBLock, _expected: bool = True) -> bool:
        """
        Lock and select the record using a record.

        :param _rec: The table rec to select with and into.
        :param _lock4update: The db lock object to use.
        :param _expected: If set to false, will not raise if record is not found.
        :return: True if selected, False if not found and _expected is set to False
        """
        _key = tSnapProvKey()
        _rec._write_key(_key)

        self.lock_one_by_key(_key, _lock4update, _expected)
        _rec._copy_from(self.rec)
        return True

    def lock_one_deft(self,
                      valuedate: datetime.date,
                      corrtype_id: str,
                      corrprov_id: str,
                      _lock4update: mettle.db.DBLock,
                      _expected: bool = True) -> bool:
        """
        Attempt to lock and select the record by it's primary key columns.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        :param _lock4update:  The db lock object to use. 
        :param _expected: bool
        """
        _key = tSnapProvKey()

        _key.valuedate = valuedate
        _key.corrtype_id = corrtype_id
        _key.corrprov_id = corrprov_id

        return self.lock_one_by_key(_key, _lock4update, _expected)

    def lock_one_by_key(self, _key: tSnapProvKey, _lock4update: mettle.db.DBLock, _expected: bool = True) -> bool:
        """
        Attempt to lock and select the record with it's primary key.

        :param _key: Primary key of the table record.
        :param _lock4update: The db lock object to use.
        :param _expected: If set to false, will not raise if record is not found.
        :return: True if selected, False if not found and _expected is set to False
        """
        with dSnapProvLockOne(self._dbcon) as _qry:
            _dex = _lock4update.retrys - 1 if _lock4update.retrys > 0 else 0

            while _dex >= 0:
                try:
                    _qry.exec(_key)
                    if not _qry.fetch():
                        if not _expected:
                            return False

                        raise mettle.lib.xMettle("LockOne failed to return a record (dSnapProv)")

                    break
                except mettle.lib.xMettle as _x:
                    if _x.get_error_code() != mettle.lib.xMettle.eCode.DBLockNoWaitFailed:
                        raise _x

                    if _dex == 0:
                        raise mettle.lib.xMettle("Could not lock SnapProv record after %d attempt(s) at %d mili second intervals!" % (
_lock4update.retrys, _lock4update.mili_seconds), errCode = mettle.lib.xMettle.eCode.DBLockNoWaitFailed)

                    if _lock4update.mili_seconds > 0:
                        time.sleep(_lock4update.mili_seconds * 0.001)
                _dex -= 1

            self.rec = _qry.orec

            return True

    def try_select_one(self) -> bool:
        """
        Attempt to select the record.

        :return: True if the record was found.
        """
        _key = tSnapProvKey()

        self.rec._write_key(_key)

        return self.try_select_one_by_key(_key)

    def try_select_one_with(self, _rec: tSnapProv) -> bool:
        """
        Attempt to select the record using a table rec.

        :param _rec: The table rec to select with and into.
        :return: True if the row as selectd.
        """
        _key = tSnapProvKey()
        _rec._write_key(_key)

        if not self.try_select_one_by_key(_key):
            return False

        _rec._copy_from(self.rec)

        return True

    def try_select_one_deft(self,
                            valuedate: datetime.date,
                            corrtype_id: str,
                            corrprov_id: str) -> bool:
        """
        Attempt to select the record by it's primary key columns.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        :return: True if the row as selectd.
        """
        _key = tSnapProvKey()

        _key.valuedate = valuedate
        _key.corrtype_id = corrtype_id
        _key.corrprov_id = corrprov_id

        return self.try_select_one_by_key(_key)

    def try_select_one_by_key(self, _key: tSnapProvKey) -> bool:
        """
        Attempt to select the record with it's primary key.

        :param _key: Primary key of the table record.
        :returns: True if row was selected.
        """
        with dSnapProvSelectOne(self._dbcon) as _qry:
            _qry.exec(_key)
            if not _qry.fetch():
                return False

            self.rec = _qry.orec

        return True

    def select_one(self) -> "dSnapProv":
        """
        Selects the record, raises and error if it does not exist.

        :return: Self for convenience.
        """
        if not self.try_select_one():
            raise mettle.lib.xMettle("SelectOne failed to return a record (dSnapProv)")

        return self

    def select_one_with(self, _rec: tSnapProv) -> "dSnapProv":
        """
        Attempt to select the record with the table record.

        :param _rec: Table record.
        :returns: Self for convenience.
        """
        if not self.try_select_one_with(_rec):
            raise mettle.lib.xMettle("SelectOne failed to return a record (dSnapProv)")

        return self

    def select_one_deft(self,
                        valuedate: datetime.date,
                        corrtype_id: str,
                        corrprov_id: str) -> "dSnapProv":
        """
        Selects the record by its primary key columns, raises and error if it does not exist.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        """
        _key = tSnapProvKey()

        _key.valuedate = valuedate
        _key.corrtype_id = corrtype_id
        _key.corrprov_id = corrprov_id

        if not self.try_select_one_by_key(_key):
            raise mettle.lib.xMettle("SelectOne failed to return a record (dSnapProv)")

        return self

    def select_one_by_key(self, _key: tSnapProvKey) -> "dSnapProv":
        """
        Attempt to select the record with it's primary key.

        :param _key: Primary key of the table record.
        :return: Self for convenience.
        """
        if not self.try_select_one_by_key(_key):
            raise mettle.lib.xMettle("SelectOne failed to return a record (dSnapProv)")

        return self

    def update_deft(self,
                    valuedate: datetime.date,
                    corrtype_id: str,
                    corrprov_id: str,
                    msg_sent: int,
                    msg_failed: int,
                    msg_retry: int,
                    avg_msg_time: float,
                    tot_msg_time: float):
        """
        Update the record by setting all column values.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        :param msg_sent: int
        :param msg_failed: int
        :param msg_retry: int
        :param avg_msg_time: float
        :param tot_msg_time: float
        """
        self.rec.valuedate = valuedate
        self.rec.corrtype_id = corrtype_id
        self.rec.corrprov_id = corrprov_id
        self.rec.msg_sent = msg_sent
        self.rec.msg_failed = msg_failed
        self.rec.msg_retry = msg_retry
        self.rec.avg_msg_time = avg_msg_time
        self.rec.tot_msg_time = tot_msg_time

        self.update()

    def update(self, irec: tSnapProv = None):
        """
        Update the record in the database with the record or irec if it is not None.

        :param irec: If not None use this record to update the database.
        """
        if irec:
            self.rec._copy_from(irec)

        with dSnapProvUpdate(self._dbcon) as _qry:
            _qry.exec(self.rec)

        if irec:
            irec._copy_from(self.rec)

    def insert_deft(self,
                    valuedate: datetime.date,
                    corrtype_id: str,
                    corrprov_id: str,
                    msg_sent: int,
                    msg_failed: int,
                    msg_retry: int,
                    avg_msg_time: float,
                    tot_msg_time: float):
        """
        Insert the record setting all column values.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        :param msg_sent: int
        :param msg_failed: int
        :param msg_retry: int
        :param avg_msg_time: float
        :param tot_msg_time: float
        """
        self.rec.valuedate = valuedate
        self.rec.corrtype_id = corrtype_id
        self.rec.corrprov_id = corrprov_id
        self.rec.msg_sent = msg_sent
        self.rec.msg_failed = msg_failed
        self.rec.msg_retry = msg_retry
        self.rec.avg_msg_time = avg_msg_time
        self.rec.tot_msg_time = tot_msg_time

        self.insert()

    def insert(self, irec: tSnapProv = None):
        """
        Insert the record in the database with the record or irec if it is not None.

        :param irec: If not None use this record to insert into the database.
        """
        if irec:
            self.rec._copy_from(irec)

        with dSnapProvInsert(self._dbcon) as _qry:
            _qry.exec(self.rec)

        if irec:
            irec._copy_from(self.rec)

    def delete_one_deft(self,
                        valuedate: datetime.date,
                        corrtype_id: str,
                        corrprov_id: str):
        """
        Delete one record by it's primary key columns.

        :param valuedate: datetime.date
        :param corrtype_id: str
        :param corrprov_id: str
        """
        _key = tSnapProvKey()

        _key.valuedate = valuedate
        _key.corrtype_id = corrtype_id
        _key.corrprov_id = corrprov_id

        self.delete_one(_key)

    def delete_one(self, irec: tSnapProvKey = None):
        """
        Delete the record by its primary key or irec if it is not None.

        :param irec: If not None use this record to delete record.
        """
        _key = tSnapProvKey()

        if irec:
            _key._copy_from(irec)
        else:
            self.rec._write_key(_key)

        with dSnapProvDeleteOne(self._dbcon) as _qry:
            _qry.exec(_key)

