import datetime
import sqlite3
from timetrack.activity import Activity


class DB:
    connection = NotImplemented

    def __init__(self, dbpath):
        self.connection = sqlite3.connect(dbpath,
            detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
        self.create_tables()

    def create_tables(self):
        c = self.connection.cursor()

        query = '''
        CREATE TABLE if not exists activities (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            activity TEXT NOT NULL,
            start_date TIMESTAMP NOT NULL,
            stop_date TIMESTAMP,
            seconds INTEGER,
            comments TEXT,
            is_deleted INTEGER DEFAULT FALSE
        )
        '''

        c.execute(query)

        # We need to add the "is_deleted" column if there is an existing table
        # without it.
        try:
            query = 'ALTER TABLE activities ADD COLUMN is_deleted INTEGER DEFAULT FALSE'
            c.execute(query)
        except sqlite3.OperationalError:
            pass

        self.connection.commit()

    def store(self, activity):
        c = self.connection.cursor()

        query = '''
        INSERT INTO activities
            (activity, start_date, stop_date, seconds)
            VALUES (?, ?, ?, ?)
        '''

        c.execute(query, (activity.name, activity.start, activity.stop, activity.seconds))
        aid = c.lastrowid

        self.connection.commit()
        return aid

    def set_stop(self, aid, stop, seconds):
        c = self.connection.cursor()

        query = '''
        UPDATE activities
            SET stop_date = ?, seconds = ?
            WHERE id = ?
        '''

        c.execute(query, (stop, seconds, aid))
        self.connection.commit()

    def update(self, act):
        if not act.id:
            return self.store(act)

        c = self.connection.cursor()

        query = '''
        UPDATE activities
            SET activity = ?, start_date = ?, stop_date = ?, seconds = ?,
                comments= ?
            WHERE id = ?
        '''

        c.execute(query, (act.name, act.start, act.stop, act.seconds,
                          act.comments, act.id))
        self.connection.commit()

        return act.id

    def delete(self, aid):
        if not aid:
            return

        c = self.connection.cursor()

        query = '''
        UPDATE activities
            SET is_deleted = TRUE
            WHERE id = ?
        '''

        c.execute(query, (aid,))
        self.connection.commit()

    def restore(self, aid):
        if not aid:
            return

        c = self.connection.cursor()

        query = '''
        UPDATE activities
            SET is_deleted = FALSE
            WHERE id = ?
        '''

        c.execute(query, (aid,))
        self.connection.commit()

    def remove_deleted(self):
        c = self.connection.cursor()

        query = 'DELETE FROM activities WHERE is_deleted = TRUE'

        c.execute(query)
        self.connection.commit()

    def get(self, aid):
        c = self.connection.cursor()

        query = '''
        Select
            id,
            activity,
            start_date as "d1 [datetime]",
            stop_date as "d2 [datetime]",
            comments
            FROM activities
            WHERE id = ?
        '''

        rows = list(c.execute(query, (aid, )))
        if not rows:
            return None
        row = rows[0]
        return Activity(id=row[0], name=row[1], start=row[2], stop=row[3],
                        comments=row[4])

    def get_last(self, limit=10, offset=0):
        c = self.connection.cursor()

        query = '''
        SELECT
            id,
            activity,
            start_date as "d1 [datetime]",
            stop_date as "d2 [datetime]",
            comments
            FROM activities
            WHERE is_deleted = FALSE
            ORDER BY start_date desc
            LIMIT {} OFFSET {}
        '''.format(limit, offset)

        for row in c.execute(query):
            yield Activity(id=row[0], name=row[1], start=row[2], stop=row[3],
                           comments=row[4])

    def get_by_name(self, name, limit=10, offset=0):
        c = self.connection.cursor()

        query = '''
        SELECT
            id,
            activity,
            start_date as "d1 [datetime]",
            stop_date as "d2 [datetime]",
            comments
            FROM activities
            WHERE activity = ? AND is_deleted = FALSE
            ORDER BY start_date desc
            LIMIT {} OFFSET {}
        '''.format(limit, offset)

        for row in c.execute(query, (name, )):
            yield Activity(id=row[0], name=row[1], start=row[2], stop=row[3],
                           comments=row[4])

    def report(self, start=None, end=None, activity=None, detailed=False):
        c = self.connection.cursor()

        if detailed:
            query = 'SELECT * FROM activities'
        else:
            query = 'SELECT activity, Sum(seconds) FROM activities'

        params = []
        where_clause = ['is_deleted = FALSE']
        query += ' WHERE '

        if activity:
            where_clause += ['activity LIKE ?']
            params += ["%{}%".format(activity)]
        if start:
            where_clause += ['start_date >= ?']
            params += [start]
        if end:
            where_clause += ['stop_date <= ?']
            params += [end]
        query += ' AND '.join(where_clause)

        if not detailed:
            query += ' GROUP BY activity'

        for row in c.execute(query, params):
            yield row

    def summary(self, day):
        c = self.connection.cursor()

        start = day.date()
        end = start + datetime.timedelta(days=1)

        query = '''
        SELECT
            SUM(seconds)
            FROM activities
            WHERE is_deleted = FALSE AND
            start_date BETWEEN '{}' and '{}'
        '''.format(start, end)

        x = list(c.execute(query))[0]
        return x[0]

    def close(self):
        self.connection.close()
