import json
import logging
import sqlite3
from os import walk, listdir, path

DEFAULT_PREFIX = "$"  # The prefix you want everyone to have if you don't define your own


class DB:
    @staticmethod
    def prepare_db(guild: int):
        try:
            connect = sqlite3.connect('user.db')
            cursor = connect.cursor()
            create_table = (f'''CREATE TABLE IF NOT EXISTS "{guild}"
                ([userid] INTEGER PRIMARY KEY, [username] TEXT, [nick] TEXT, [isbot] BOOL, [track] TEXT)
                ''')
            cursor.execute(create_table)
            cursor.close()
        except sqlite3.Error as _error:
            logging.error("failed to connect db", _error)

    @staticmethod
    def work_with_db(db_func, data_turple):
        try:
            connect = sqlite3.connect('user.db')
            cursor = connect.cursor()
            cursor.execute(db_func, data_turple)
            connect.commit()
            cursor.close()

        except sqlite3.Error as _error:
            logging.error("failed to connect db", _error)

    @staticmethod
    def fill_bd(name: str, userid: int, isbot: bool, nick: str, guild: int):
        sqlite_insert_with_param = (f"""INSERT OR IGNORE INTO "{guild}"
                              (username, userid, nick, isbot) 
                              VALUES (?, ?, ?, ?)""")
        data_tuple = (name, userid, nick, isbot)
        DB.work_with_db(sqlite_insert_with_param, data_tuple)

    @staticmethod
    def add_audio(guild: int, user: int, audio: str):
        sql_update_query = f"""UPDATE "{guild}" set track = ? where userid = ?"""
        data_tuple = (audio, user)
        DB.work_with_db(sql_update_query, data_tuple)

    @staticmethod
    def read_db(guild: int, user: int):
        try:
            sql_con = sqlite3.connect("user.db")
            cursor = sql_con.cursor()
            sql_read = f"""SELECT * FROM "{guild}" where userid = {user}"""
            cursor.execute(sql_read)
            record = cursor.fetchone()
            return record[4]

        except sqlite3.Error as _error:
            logging.error("Failed to read sqlite table", _error)


class CogsPrepare:
    @staticmethod
    def cog_list():
        cogs_list = []
        for _filename in listdir('./cogs'):
            if _filename.endswith('.py'):
                cogs_list.append(_filename[:-3])
        return cogs_list

    @staticmethod
    def cogs_dict():
        cog_dict = {}
        for _cog in CogsPrepare.cog_list():
            cog_dict.update({f'{_cog}': f'{_cog}'})
        return cog_dict

    @staticmethod
    async def work_with_cogs(what_do, bot):
        for _filename in CogsPrepare.cog_list():
            if what_do == "load":
                bot.load_extension(f'cogs.{_filename}')
            elif what_do == 'unload':
                bot.unload_extension(f'cogs.{_filename}')
            elif what_do == 'reload':
                bot.reload_extension(f'cogs.{_filename}')
            logging.info(f'{what_do}ing cog {_filename}')


class Commands:
    @staticmethod
    def check_json():
        if not path.isfile('prefix.json'):
            with open('prefix.json', 'w+', encoding='utf-8') as f:
                f.write("")
            f.close()

    @staticmethod
    async def set_prefix(inter, prefix: str):
        await Commands.write_json(inter.guild.id, "prefix", prefix)

    @staticmethod
    def list_files(fold: str):
        fl = []
        for filenames in walk(fold):
            fl.extend(filenames)
            break
        files = {}
        for x in fl[2]:
            files[x] = x

        return files

    @staticmethod
    async def read_json(guild: int, param: str):
        with open('prefix.json', 'r', encoding='utf-8') as fp:  # Open the JSON
            parameter = None
            try:
                _json = json.load(fp)  # Load the custom prefixes
            except:
                _json = {}
        if guild:  # If the guild exists
            try:
                guild_conf = _json[f"{guild}"]
                try:
                    parameter = guild_conf[f"{param}"]
                except:
                    pass
            except:
                pass
        fp.close()
        return parameter

    @staticmethod
    async def write_json(guild: int, param_name: str, param: str or int):
        with open('prefix.json', 'r', encoding='utf-8') as _f:
            try:
                _json = json.load(_f)
            except json.decoder.JSONDecodeError:
                _json = {}
            _f.close()
        try:
            _guild = _json[f'{guild}']
        except KeyError:
            _json.update({f'{guild}': {}})
        _guild = _json[f'{guild}']
        _guild.update({f'{param_name}': f'{param}'})

        with open('prefix.json', 'w', encoding='utf-8') as _f:
            json.dump(_json, _f, indent=4)
            _f.close()

    @staticmethod
    def determine_prefix(bot, msg):
        with open('prefix.json', 'r', encoding='utf-8') as fp:  # Open the JSON
            parameter: str
            try:
                from json import load
                _json = load(fp)  # Load the custom prefixes
            except:
                _json = {}
        if msg.guild:  # If the guild exists
            try:
                parameter = _json[f"{msg.guild.id}"]["prefix"]  # Read prefix from json if is setted up
            except:
                parameter = DEFAULT_PREFIX
            print(parameter)
            return parameter
