# Source code of the Ubuntu-it website
# Copyright (C) 2015  Pietro Albini <pietroalbini@ubuntu.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; witout even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import threading
import sqlite3

import pkg_resources


_LOCAL = threading.local()


class Database:

    def __init__(self, path):
        self._path = path

    def init(self):
        """Initialize the database"""
        db_version = int(self.query("PRAGMA user_version;")[0][0])

        cursor = self.cursor()
        if db_version == 0:
            cursor.executescript("""
                CREATE TABLE migrations (name TEXT PRIMARY KEY);
                PRAGMA user_version = 1;
            """)

        applied = [m[0] for m in self.query("SELECT * FROM migrations;")]
        for name, sql in MIGRATIONS:
            if name in applied:
                continue
            cursor.executescript(sql)
            cursor.execute("INSERT INTO migrations (name) VALUES (?)", [name])

        cursor.connection.commit()

    def cursor(self):
        """Get a new cursor"""
        if not hasattr(_LOCAL, "db"):
            _LOCAL.db = sqlite3.connect(self._path)
        return _LOCAL.db.cursor()

    def query(self, query, *params, update=False):
        """Make a new query against the db"""
        cursor = self.cursor()
        cursor.execute(query, params)

        try:
            if update:
                cursor.connection.commit()
            else:
                return cursor.fetchall()
        finally:
            cursor.close()

    def update(self, query, *params):
        """Make a new update query against the db"""
        self.query(query, *params, update=True)


MIGRATIONS = [
    ("create_auth_sessions_table", """
        CREATE TABLE auth_sessions (
            id TEXT PRIMARY KEY,
            nickname TEXT NOT NULL,
            teams TEXT NOT NULL,
            ip TEXT NOT NULL
        );
    """),

    ("add_auth_sessions_expires_at_column", """
        ALTER TABLE auth_sessions ADD COLUMN expires_at INTEGER;
    """),

    ("add_auth_sessions_created_at_column", """
        ALTER TABLE auth_sessions ADD COLUMN created_at INTEGER;
    """),

    ("add_actions_table", """
        CREATE TABLE actions (
            session TEXT NOT NULL,
            date INTEGER NOT NULL,
            message TEXT NOT NULL
        );
    """),
]
