import random, secrets, datetime, uuid
from slugify import slugify
from common import log

def create_or_get_and_update_last_event(self, table, event_type, channel_name=None, user_name=None, event_content=None, event_subject_name=None):
    if table == 'channel':
        name = channel_name
    if table == 'user':
        name = user_name
    record = self.db.one('SELECT * FROM rotbot_' + table + ' WHERE LOWER(name)=LOWER(%(name)s) AND network_id=%(network_id)s', name=name, network_id=self.network.id)   # Look up the record.

    if record:  # On record.
        fields = 'name=%(name)s, last_event_type=%(last_event_type)s' # All required fields
        event_channel_id = None
        event_user_id = None
        event_subject_id = None
        if 'event_channel' in locals():
            event_channel_id = get_channel_id(self, channel_name)
            fields += ', last_event_channel_id=%(last_event_channel_id)s'
        if 'event_user' in locals():
            event_user_id = get_user_id(self, user_name)
            fields += ', last_event_user_id=%(last_event_user_id)s'
        if 'event_content' in locals():
            fields += ', last_event_content=%(last_event_content)s'
        if 'event_subject' in locals():
            event_subject_id = get_user_id(self, user_name)
            fields +- ', last_event_subject_id=%(last_event_subject_id)s'
        self.db.run(    # Correct capitalisation and update last event.
            'UPDATE rotbot_' + table + ' SET ' + fields + ' WHERE LOWER(name)=LOWER(%(name)s) AND network_id=%(network_id)s',
            name=name,
            network_id=self.network.id,
            last_event_type=event_type,
            last_event_channel_id=event_channel_id,
            last_event_user_id=event_user_id,
            last_event_content=event_content,
            last_event_subject_id=event_subject_id)

    else:   # Not on record.
        new_slug = slugify('%s-%s' % (name, self.network.name), max_length=50) # Create a slug from the name.
        slug_exists = self.db.one('SELECT id FROM rotbot_' + table + ' WHERE slug=%(slug)s AND network_id=%(network_id)s', slug=new_slug, network_id=self.network.id)   # Try to lookup a record with the proposed slug.

        # Keep adding random letters from the name to the slug until it is unique.
        while slug_exists and slug_exists <= 50:
            new_slug = new_slug + random.choice(name)
            slug_exists = self.db.one('SELECT id FROM rotbot_' + table + ' WHERE slug=%(slug)s AND network_id=%(network_id)s', slug=new_slug, network_id=self.network.id)
            log.notice('Requested slug already taken on table %s with network %s: %s' % (table, self.network.name, new_slug))
        while slug_exists:
            new_slug = name + str(uuid.uuid4())
            slug_exists = self.db.one('SELECT id FROM rotbot_' + table + ' WHERE slug=%(slug)s AND network_id=%(network_id)s', slug=new_slug, network_id=self.network.id)
            log.warn('Please clean database. Newly generated uuid4 already taken on table %s with network %s: %s' % (table, self.network.name, new_slug))

        fields = 'name, network_id, slug, last_event_type, last_event_datetime'
        values = '%(name)s, %(network_id)s, %(slug)s, %(last_event_type)s, %(last_event_datetime)s'
        event_datetime = datetime.datetime.now
        event_channel_id = None
        event_user_id = None
        event_subject_id = None
        if 'event_channel' in locals():
            event_channel_id = get_channel_id(self, channel_name)
            fields += ', last_event_channel_id'
            values += ', %(last_event_channel_id)s'
        if 'event_user' in locals():
            event_user_id = get_user_id(self, user_name)
            fields += ', last_event_user_id'
            values += ', %(last_event_user_id)s'
        if 'event_content' in locals():
            fields += ', last_event_content'
            values += ', %(last_event_content)s'
        if 'event_subject' in locals():
            event_subject_id = get_user_id(self, user_name)
            fields += ', last_event_subject_id'
            values += ', %(last_event_subject_id)s'
        if table == 'channel':
            fields += ', autojoin, key, games, statistic_commands, chat'
            values += ', %(autojoin)s, %(key)s, %(games)s, %(statistic_commands'
            self.db.run(    # Create record.
                'INSERT INTO rotbot_' + table + ' (' + fields + ') VALUES (' + values + ')s, %(chat)s)',
                name=name,
                network_id=self.network.id,
                slug=new_slug,
                last_event_type=event_type,
                last_event_datetime=datetime.datetime.now(),
                last_event_channel_id=event_channel_id,
                last_event_user_id=event_user_id,
                last_event_content=event_content,
                last_event_subject_id=event_subject_id,
                autojoin=False,
                key='',
                games=False,
                statistic_commands=False,
                chat=False,
            )
        else:
            fields += ', xp_spent, level, coin, coin_given, coin_spent, ap_spent, karma_correction, no_chat'
            values += ', %(xp_spent)s, %(level)s, %(coin)s, %(coin_given)s, %(coin_spent)s, %(ap_spent)s, %(karma_correction)s, %(no_chat)s'
            self.db.run(    # Create record.
                'INSERT INTO rotbot_' + table + ' (' + fields + ') VALUES (' + values + ')',
                name=name,
                network_id=self.network.id,
                slug=new_slug, last_event_type=event_type,
                last_event_datetime=datetime.datetime.now(),
                last_event_channel_id=event_channel_id,
                last_event_user_id=event_user_id,
                last_event_content=event_content,
                last_event_subject_id=event_subject_id,
                xp_spent=0,
                level=0,
                coin=0,
                coin_given=0,
                coin_spent=0,
                ap_spent=0,
                karma_correction=0,
                no_chat=False,
            )
        record = self.db.one('SELECT * FROM rotbot_' + table + ' WHERE slug=%(slug)s', slug=new_slug)   # Lookup newly created record to return to call..
    return record


def get_owners(self):
    return self.db.all('SELECT * FROM rotbot_owner')

def get_channel_id(self, channel_name):
    return self.db.one('SELECT id FROM rotbot_channel WHERE network_id=%(network_id)s AND LOWER(name)=LOWER(%(channel_name)s)', network_id=self.network.id, channel_name=channel_name)

def get_channel_slug(self, channel_name):
    return self.db.one('SELECT slug FROM rotbot_channel WHERE network_id=%(network_id)s AND LOWER(name)=LOWER(%(channel_name)s)', network_id=self.network.id, channel_name=channel_name)

def get_channel_setting_statistic_commands(self, channel_name):
    return self.db.one('SELECT statistic_commands FROM rotbot_channel WHERE LOWER(name)=LOWER(%(channel_name)s) AND network_id=%(network_id)s', channel_name=channel_name, network_id=self.network.id)

def get_channel_setting_game_commands(self, channel_name):
    return self.db.one('SELECT games FROM rotbot_channel WHERE name=LWOER(%(channel_name)s) AND network_id=%(network_id)', channel_name=channel_name, network_id=self.network.id)

def get_autojoin_channels(self):
    return self.db.all('SELECT name FROM rotbot_channel WHERE network_id=%(network_id)s AND autojoin=True', network_id=self.network.id)

def update_channel_last_event(self, channel, event_type, event_content):
    self.db.run('UPDATE rotbot_channel SET last_event_type=%(last_event_type)s, last_event_content=%(last_event_content)s WHERE channel.id=%(channel_id)s', last_event_type=event_type, last_event_content=event_content)

def create_tempchannelkey(self, channel_id):
    temp_key = secrets.token_urlsafe(40)[:40]
    self.db.run('INSERT INTO rotbot_tempchannelkey (key, network_id, channel_id, created) VALUES (%(key)s, %(network_id)s, %(channel_id)s, %(created)s)', key=temp_key, network_id=self.network.id, channel_id=channel_id, created=datetime.datetime.now())
    return temp_key

def update_message_statistics(self, type, channel, user):
    if not self.db.one('SELECT id FROM rotbot_' + type + ' WHERE network_id=%(network_id)s AND channel_id=%(channel_id)s AND user_id=%(user_id)s', network_id=self.network.id, channel_id=channel.id ,user_id=user.id):  # Not on record.
        self.db.run('INSERT INTO rotbot_' + type + ' (network_id, channel_id, user_id, amount) VALUES (%(network_id)s, %(channel_id)s, %(user_id)s, 1)', network_id=self.network.id, channel_id=channel.id ,user_id=user.id)   # Create record.
    else:   # On record.
        self.db.run('UPDATE rotbot_' + type + ' SET amount = amount +1 WHERE network_id=%(network_id)s AND channel_id=%(channel_id)s AND user_id=%(user_id)s', network_id=self.network.id, channel_id=channel.id ,user_id=user.id)  # Increment record.

def increment_join(self, channel, user):
    if not self.db.one('SELECT id FROM rotbot_join WHERE network_id=%(network_id)s AND channel_id=%(channel_id)s AND user_id=%(user_id)s', network_id=self.network.id, channel_id=channel.id, user_id=user.id):   # No record yet
        self.db.run('INSERT INTO rotbot_join (network_id, channel_id, user_id, amount) VALUES (%(network_id)s, %(channel_id)s, %(user_id)s, 1)', network_id=self.network.id, channel_id=channel.id, user_id=user.id)   # Create record.
    else:
        self.db.run('UPDATE rotbot_join SET amount = amount + 1 WHERE network_id=%(network_id)s AND channel_id=%(channel_id)s AND user_id=%(user_id)s', network_id=self.network.id, channel_id=channel.id, user_id=user.id)   # Update existing record.

def get_top_users(self, sort):
    return self.db.all('SELECT id, name, level, xp_spent, coin FROM rotbot_user WHERE network_id=%(network_id)s ORDER BY ' + sort + ' DESC LIMIT 3 ', network_id=self.network.id)

def levelup_user(self, user, xp):
    self.db.run('UPDATE rotbot_user SET level=level+1, xp_spent=xp_spent+%(xp)s, ap_spent=ap_spent+1 WHERE id=%(user_id)s', xp=xp, user_id=user.id)
    self.db.run('UPDATE rotbot_user SET coin=coin+0.3 WHERE level>0 AND user_id=%(user_id)s', (self.user.id))

def get_user_gamestats(self, user):
    return self.db.one('SELECT xp_spent, level, coin, coin_given, coin_spent, ap_spent, karma_correction FROM rotbot_user WHERE id=%(id)s', id=user.id)

def get_user(self, user_name):
    return self.db.one('SELECT * FROM rotbot_user WHERE network_id=%(network_id)s AND LOWER(name)=LOWER(%(user_name)s)', network_id=self.network.id, user_name=user_name)

def get_user_id(self, user_name):
    return self.db.one('SELECT id FROM rotbot_user WHERE network_id=%(network_id)s AND LOWER(name)=LOWER(%(user_name)s)', network_id=self.network.id, user_name=user_name)

def get_userl_slug(self, user_name):
    return self.db.one('SELECT slug FROM rotbot_user WHERE network_id=%(network_id)s AND LOWER(name)=LOWER(%(user_name)s)', network_id=self.network.id, user_name=user_name)

def get_user_name(self, user_id):
    return self.db.one('SELECT name FROM rotbot_user WHERE id=%(id)s', id=user_id)

def get_user_total_joins(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_join WHERE user_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_kicks(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_kick WHERE kicker_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_kicked(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_kick WHERE kicked_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_messages(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_message WHERE user_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_actions(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_action WHERE user_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_notices(self, user):
    recordset = self.db.all('SELECT amount FROM rotbot_notice WHERE user_id=%(user_id)s AND network_id=%(network_id)s', user_id=user.id, network_id=self.network.id)
    return total_amount_in_recordset(recordset)

def get_user_total_curseword_added(self, user):
    recordset = self.db.all('SELECT id FROM rotbot_curseword WHERE irc_user_id=%(user_id)s ', user_id=user.id)
    return recordset.count(recordset)

def get_user_total_curseadjective_added(self, user):
    recordset = self.db.all('SELECT id FROM rotbot_curseadjective WHERE irc_user_id=%(user_id)s', user_id=user.id)
    return recordset.count(recordset)

def random_curse(self):
    adjective = self.db.one('SELECT word FROM rotbot_curseadjective ORDER BY RANDOM() LIMIT 1')
    curse = self.db.one('SELECT word FROM rotbot_curseword ORDER BY RANDOM() LIMIT 1')
    return '%s %s' % (adjective, curse)

def get_curse(self, word):
    return self.db.one('SELECT * FROM rotbot_curseword WHERE LOWER(word)=LOWER(%(word)s)')

def add_curseword(self, word, user_id):
    user_id = get_user_id(self, user_name)
    return self.db.run('INSERT INTO rotbot_curseword (word, created, irc_user_id, banned) VALUES (LOWER(%(word)s), %(created)s, %(irc_user_id)s, %(banned)s)', word=word, created=datetime.datetime.now, irc_user_id=user_id, banned=False)


# Common.

def total_amount_in_recordset(recordset):
    amount = 0
    for record in recordset:
        #amount += record.amount
        amount += record
    return amount
