import os
import ydb


class YdbTable(object):
    """Base class for YdbTables

    :param object: [description]
    :type object: [type]
    :raises NotImplementedError: [description]
    :return: [description]
    :rtype: [type]
    """

    def __init__(self, ydb_manager, database, table):
        """
        Args:
            table(str) : 'tmp/id_to_cid_transfered_table'
        """
        self._ydb_manager = ydb_manager
        self.database = database
        self.table = table
        self.full_table_path = os.path.join(self.database, self.table)
        self.folder = self.full_table_path[:self.full_table_path.rfind('/')]

        self._session = None
        self._insert_key = '$records'

    def _init_session(self):
        return self._ydb_manager.pool.acquire()

    def create(self):
        raise NotImplementedError()

    def insert(self, records):
        query_params = {self._insert_key: records}
        self._insert(query_params)

    class Record():
        __slots__ = ()

    def describe(self):
        with self._init_session() as session:
            result = session.describe_table(self.full_table_path)
            print('\n> describe table: {}'.format(self.table))
            for column in result.columns:
                print('column_name: {}; {}'.format(column.name, str(column.type.item).strip()))

    def _insert(self, query_params):
        # TODO: Добавить обработку ошибок
        with self._init_session() as session:
            prepared_query = session.prepare(self._insert_request.format(database=self.database, table=self.table))
            session.transaction(ydb.SerializableReadWrite()).execute(
                prepared_query,
                query_params,
                commit_tx=True,
            )

    def _get_one(self, query_params):
        for rec in self._get(query_params):
            return rec
        return None

    def _get(self, query_params):
        # TODO: Добавить обработку ошибок
        # new transaction in serializable read write mode
        # if query successfully completed you will get result sets.
        # otherwise exception will be raised
        with self._init_session() as session:
            query = self._select_request.format(
                database=self.database,
                table=self.table
            )
            prepared_query = session.prepare(query)

            result_sets = session.transaction(ydb.SerializableReadWrite()).execute(
                prepared_query,
                query_params,
                commit_tx=True
            )
            for row in result_sets[0].rows:
                yield self.Record(**row)
