#!/usr/bin/python
 # -*- coding: utf-8 -*-

from slackclient import SlackClient
import time
import sys
import os

import sqlite3
import importlib

import seccyconfig

database = seccyconfig.database 

BOT_ID = seccyconfig.BOT_ID
BOT_NAME = seccyconfig.BOT_NAME
SLACK_BOT_TOKEN = seccyconfig.SLACK_BOT_TOKEN
BOT_OPML = seccyconfig.BOT_OPML
BOT_PATH = seccyconfig.BOT_PATH

AT_BOT = "<@" + BOT_ID + ">"


slack_client = SlackClient(SLACK_BOT_TOKEN)

owners = []
owners_name = []

'''
    The main part should never reload. Move as much as possible to pluggable modules

'''

class LoadableModule:

    def __init__(self, keyw, help, modobj):
        self.modobj = modobj
        self.keyw = keyw
        self.help = help


class CommonFunction:

    def setOwners(self, owners):
        self.owners = owners

    def getOwners(self):
        return self.owners

    def closeDBConnectionNoCommit(self, con):
        con.close()

    def closeDBConnection(self, con):
        con.commit()
        con.close()

    def getDBConnection(self):
        return sqlite3.connect(database)

keywords = {}
commonfunctions = CommonFunction()
commonfunctions.setOwners(owners)

#loadablemodules = {}

def register_keyword(word, moduleobj):
    global keywords
    try:
        keywords.pop(word)
    except:
        print "Nothing to pop"
    keywords[word] = moduleobj


def load_module(loadmodule):
    try:
        print loadmodule
        tempobj = importlib.import_module("commandmodules." + str(loadmodule[:-3]))
        keyword = tempobj.command_to_trigger
        if keyword in keywords.keys():
            reload(keywords[keyword]) # str(loadmodule[:-3]))
            print "hit the reload"
        else:
            register_keyword(keyword, tempobj)
        tempobj.initModule(commonfunctions)

        return 1
    except:
        return -1

def load_all_modules():

    # look at the directory "modules"
    # find all .py files
    # load them one at a time
    modules_to_load = []
    for file in os.listdir(os.path.join(BOT_PATH, "commandmodules")):
        if file[-3:] == ".py" and file[:-3] != "__init__":
            try:
                tempobj = importlib.import_module("commandmodules." + str(file[:-3]))
                keyword = tempobj.command_to_trigger
                tempobj.initModule(commonfunctions)
                register_keyword(keyword, tempobj)
                print "Loaded module: " + keyword
            except:
                print "Loading failed for " + str(file)


def load_owners():

    global owners
    owners = []
    global owners_name
    owners_name = []

    con = commonfunctions.getDBConnection()
    cur = con.cursor()

    cur.execute("SELECT userid, username from slackbot_owners")

    for owner in cur.fetchall():
        owners.append(owner[0])
        owners_name.append(owner[1])

    commonfunctions.closeDBConnectionNoCommit(con)
    commonfunctions.setOwners(owners)

def load_users():

    con = commonfunctions.getDBConnection()
    cur = con.cursor()

    api_call = slack_client.api_call("users.list")
    if api_call.get('ok'):
        users = api_call.get('members')
        for user in users:
            if 'name' in user:
                id = None
                try:
                    sql = "SELECT id from slackbot_knownusers WHERE username LIKE ? and userid LIKE ?"
                    data = (user.get('name'), user.get('id'))

                    cur.execute(sql, data)
                    id = cur.fetchone()[0]

                    # update row
                    sql = "UPDATE slackbot_knownusers SET lastseen = ? WHERE username LIKE ? and userid LIKE ?"
                    data = (str(int(time.time())), user.get('name'), user.get('id'))
                    cur.execute(sql, data)
                except:
                    # new user
                    sql = "INSERT INTO slackbot_knownusers (username, userid, lastseen) VALUES (?,?,?)"
                    data = (user.get('name'), user.get('id'), str(int(time.time())))

                    cur.execute(sql,data)

            con.commit()
    commonfunctions.closeDBConnection(con)

def handle_command(command, channel, callfrom):
    response = ""
    if command.startswith("help"):
        # loop through it all and build the new help
        response = '''
This is my help page, this is autogenerated so it might differ over time. * indicates admin rights required
-* load_module <module>
    Load a new module
-* addadmin <username>
    Add a new admin user
-* removeadmin <username>
    Remove an admin user
-* listadmins
    List the current list of admins
- help
    This blob of text

---- Modules ----
'''
        for ke in keywords.keys():
            response = response + "-"
            if keywords[ke].command_required_admin:
                response = response + "*"
            response = response + " " + str(keywords[ke].command_to_trigger) + "\n\t" + str(keywords[ke].command_help) + "\n"

    elif command.startswith("listadmins"):
        parts = command.split(' ')
        response = "I'm enslaved by: \n"
        for i in owners_name:
            response = response + i + "\n"

    elif command.startswith("load_module"):
        if callfrom in owners:
            parts = command.split(' ')
            module_to_add = parts[1] + ".py"
            ok = load_module(module_to_add)
            if ok == 1:
                response = "The module is loaded"
            else:
                response = "The loading of the module failed"
        else:
            response = "You are not an admin... Nice try"

    elif command.startswith("addadmin"):
        if callfrom in owners:
            parts = command.split(' ')
            username_to_add = parts[1]
            userid_given = False
            if username_to_add.startswith('<'):
                # this is a userid
                userid_given = True
                username_to_add = username_to_add.replace('<@','').replace('>','').upper()
            try:
                con = commonfunctions.getDBConnection()
                cur = con.cursor()
                if not userid_given:
                    sql = "SELECT userid from slackbot_knownusers WHERE username LIKE ?"
                    data = (username_to_add, )
                    cur.execute(sql, data)

                    userid = cur.fetchone()[0]
                    username = username_to_add
                else:
                    sql = "SELECT username from slackbot_knownusers WHERE userid LIKE ?"
                    data = (username_to_add,)
                    cur.execute(sql, data)

                    username = cur.fetchone()[0]
                    userid = username_to_add

                sql = "INSERT INTO slackbot_owners (username, userid) VALUES (?,?)"
                data = (username, userid)

                cur.execute(sql, data)
                commonfunctions.closeDBConnection(con)

                load_owners()
                response = "User added"

            except:
                response = "Something is wrong. Is the username correct?"
        else:
            response = "You are not an admin... Nice try"

    elif command.startswith("removeadmin"):
        if callfrom in owners:
            parts = command.split(' ')
            username_to_remove = parts[1]
            userid_given = False
            if username_to_remove.startswith('<'):
                # this is a userid
                userid_given = True
                username_to_remove = username_to_remove.replace('<@','').replace('>','').upper()
            try:
                con = commonfunctions.getDBConnection()
                cur = con.cursor()
                if not userid_given:
                    sql = "SELECT userid from slackbot_knownusers WHERE username LIKE ?"
                    data = (username_to_remove, )
                    cur.execute(sql, data)

                    userid = cur.fetchone()[0]
                    username = username_to_remove
                else:
                    sql = "SELECT username from slackbot_knownusers WHERE userid LIKE ?"
                    data = (username_to_remove,)
                    cur.execute(sql, data)
                    username = cur.fetchone()[0]
                    userid = username_to_remove

                sql = "DELETE FROM slackbot_owners WHERE username LIKE ? AND userid LIKE ?"
                data = (username, userid)

                cur.execute(sql, data)
                commonfunctions.closeDBConnection(con)
                load_owners()
                response = "Byebye! " + username + " is gone!"

            except:
                response = "Something is wrong. Is the username correct?"
        else:
            response = "You are not an admin... Nice try"

    else:
        # we see if the command is a keyword
        parts = command.split(' ')
        try:
            response = keywords[parts[0]].handle_command(command, channel, callfrom)
        except:
            print "I believe it is an unknown command. "
            response = "Command unknown or something went wrong!"

    slack_client.api_call("chat.postMessage",channel=channel, text=response, as_user=True)



def parse_slack_output(slack_rtm_output):
    output_list = slack_rtm_output
    if output_list and len(output_list) > 0:
        for output in output_list:
            if output and 'text' in output and AT_BOT in output["text"] and output["text"].split(' ')[0] == AT_BOT:
                return output['text'].split(AT_BOT)[1].strip(), output['channel'], output['user']
    return None, None, None



if __name__ == "__main__":

    READ_WEBSOCKET_DELAY = 1
    if slack_client.rtm_connect():
        print "Connected"

        load_owners()
        load_users()

        # load different modules
        load_all_modules()

        counter=0
        while True:
            command, channel, callfrom = parse_slack_output(slack_client.rtm_read())
            if command and channel:
                handle_command(command, channel, callfrom)
	    if counter % 10 == 0:
               load_users()
               counter = 0
            time.sleep (READ_WEBSOCKET_DELAY)
            counter = counter + 1
    else:
        print "Something barfed"
