import logging
import sqlite3
import sys

logger = logging.getLogger("database")


class Database:
    def __init__(self, dbstr: str):
        # If true, sqlite connections can be shared across
        # threads, and so we can pass check_same_thread=False safely.
        assert self._sqlite_is_threadsafe()
        self.conn = sqlite3.connect(
            dbstr, check_same_thread=False, isolation_level=None
        )
        self.conn.row_factory = sqlite3.Row

        self.init_db()

    def _sqlite_is_threadsafe(self) -> bool:
        """
        Check that it is safe to use the Database from multiple threads at the
        same time. This should be as easy as checking `sqlite3.threadsafety`,
        but that value was historically hardcoded. The real value is available
        by querying the compile options from sqlite.
        """
        if sys.hexversion >= 0x030B00F0:
            return sqlite3.threadsafety == 3
        else:
            conn = sqlite3.connect(":memory:")
            opt = conn.execute(
                "SELECT * FROM pragma_compile_options WHERE compile_options LIKE 'THREADSAFE=%'"
            ).fetchone()
            return "THREADSAFE=1" in opt

    def init_db(self):
        """
        Set up the database, creating the requisite tables if they do not exist.
        """
        logger.info("initialising database...")

        self.conn.execute(
            "CREATE TABLE IF NOT EXISTS epigrams (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT)"
        )

        logger.info("initialised.")

    def execute(self, *args, **kwargs):
        return self.conn.execute(*args, **kwargs)

    def commit(self):
        self.conn.commit()
