import time
from datacloud.dev_utils.yt import yt_utils
from datacloud.dev_utils.logging.logger import get_basic_logger

logger = get_basic_logger(__name__)


__all__ = [
    'ConfigTable',
    'LogTable'
]


class ConfigTable(object):
    def __init__(self, table_path, schema, yt_client=None):
        self.table_path = table_path
        self.schema = schema
        self._yt_client = yt_client or yt_utils.get_yt_client()

    def exists(self):
        return self._yt_client.exists(self.table_path)

    def create_table(self, force=False):
        yt_utils.DynTable.create_table(self.table_path, self.schema, self._yt_client, force=force)

    def insert_records(self, records):
        yt_utils.DynTable.insert_row(self.table_path, self._yt_client, records)

    def insert_records_with_retry(self, records, n_retry=10):
        e = Exception('Failed `insert_record`')
        while n_retry > 0:
            try:
                self.insert_records(records)
                return
            except Exception as e:
                logger.exception(e)
                time.sleep(5)
                n_retry -= 1
        raise e

    def remove_records(self, records):
        yt_utils.DynTable.remove_row(self.table_path, self._yt_client, records)

    def list_records(self):
        request = '* FROM [{table_path}]'.format(table_path=self.table_path)
        return self.request_records(request)

    def request_records(self, request):
        return yt_utils.DynTable.list_rows(self._yt_client, request)

    def get_record(self, request):
        generator = self.request_records(request)
        try:
            return next(generator)
        except StopIteration:
            return None

    def get_records_by_params(self, param_dict):
        return yt_utils.DynTable.get_rows_from_table(self.table_path, param_dict, self._yt_client)

    def get_record_by_params(self, param_dict):
        generator = self.get_records_by_params(param_dict)
        try:
            return next(generator)
        except StopIteration:
            return None

    def update_record(self, request, data):
        record = self.get_record(request)
        for key, val in data.items():
            record[key] = val
        self.insert_records([record])


class LogTable(ConfigTable):
    pass
