import sqlite3
import asyncio
from pymongo import MongoClient
import aiomysql
from aiomysql.cursors import DictCursor

from utils import ReadConf
class Proxy(object):
    def __init__(self):
        self._host = ""
        self._port = 0000

    @property
    def host(self):
        return

    @host.setter
    def host(self, value):
        self._host = value

    @property
    def port(self):
        return

    @port.setter
    def port(self, value):
        if not isinstance(value, int):
            return TypeError(f"端口必须是一个int:{value}")
        self._port = value

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

class DataBaseBySqlite3(Proxy):
    def __init__(self):
        super(DataBaseBySqlite3, self).__init__()
        self._path = ""
        self._conn = None

    @property
    def path(self):
        return self._path

    @path.setter
    def path(self, value):
        self._path = value

    def connect(self):
        self._conn = sqlite3.connect(self._path)
        self._conn.row_factory = dict_factory

    def close(self):
        self._conn.close()

    def insert(self, table, data):
        field = ",".join(tuple(data.keys()))
        values = tuple(data.values())
        t = ','.join("?" * len(values))
        sql = f'''insert into {table} ({field}) values ({t})'''
        cur = self._execute(sql, values)
        self._conn.commit()
        return cur.lastrowid

    def query(self, table, field, where):
        whereSrt = []
        fieldStr = ", ".join(field)
        for k, v in where.items():
            whereSrt.append(f"{k} = ?")
        sql = f'''select {fieldStr} from {table} where {' and '.join(whereSrt)}'''
        cur = self._execute(sql, tuple(where.values()))
        return cur.fetchall()

    def update(self, table, data, where):
        dataList, whereList = [], []
        for k, v in data.items():
            dataList.append(f"{k} = ?")

        for k, v in where.items():
            whereList.append(f"{k}= ?")
        sql = f'''update {table} set {','.join(dataList)} where {' and '.join(whereList)} '''
        param = tuple(list(data.values())+list(where.values()))
        cur = self._execute(sql, param)
        self._conn.commit()
        return cur.rowcount

    def execute(self, sql, *args):
        cur = self._execute(sql, *args)
        self._conn.commit()
        return cur

    def _execute(self, sql, *args):
        cur = self._conn.cursor()
        cur.execute(sql, *args)
        return cur


class DataBaseByMysql(Proxy):
    def __init__(self):
        super(DataBaseByMysql, self).__init__()
        self._path = ""
        self._poll = None
        self.MIDDLEWARE_NAME = "DATABASE_MIDDLEWARE_BY_PARK"

    async def connect(self):
        conf = ReadConf(self.MIDDLEWARE_NAME)
        self._poll = await aiomysql.create_pool(
                    cursorclass=DictCursor,
                    host=conf.get("HOST"),
                    port=conf.get("PORT"),
                    user=conf.get("USER"),
                    password=conf.get("PASSWORD"),
                    db=conf.get("DATABASE_NAME"),
                )

    async def close(self):
        # self._poll.close()
        await self._pool.wait_closed()

    async def insert(self, table, data):
        field = ",".join(tuple(data.keys()))
        values = tuple(data.values())
        a = []
        for i in range(len(values)):
            a.append("%s")
        t = ','.join(a)
        sql = f'''insert into {table} ({field}) values ({t})'''
        cur = await self._execute(sql, values)
        return cur.lastrowid

    async def query(self, table, field, where):
        whereSrt = []
        fieldStr = ", ".join(field)
        for k, v in where.items():
            whereSrt.append(f"{k} = %s")
        sql = f'''select {fieldStr} from {table} where {' and '.join(whereSrt)}'''
        cur = await self._execute(sql, tuple(where.values()))
        return await cur.fetchall()

    async def update(self, table, data, where):
        dataList, whereList = [], []
        for k, v in data.items():
            dataList.append(f"{k} = %s")

        for k, v in where.items():
            whereList.append(f"{k}= %s")
        sql = f'''update {table} set {','.join(dataList)} where {' and '.join(whereList)} '''
        param = tuple(list(data.values())+list(where.values()))
        cur = await self._execute(sql, param)
        return cur.rowcount

    async def execute(self, sql, param):
        cur = await self._execute(sql, param)
        return cur

    async def _execute(self, sql, param):
        async with self._poll.acquire() as conn:
            cur = await conn.cursor()
            await cur.execute(sql,param)
            await conn.commit()
            return cur



class MongoClientProxy(Proxy):
    def __init__(self):
        super().__init__()
        self.maxPoolSize = 10
        self.client = None

    def conn(self):
        self.client =  MongoClient(self.host, self.port, maxPoolSize=self.maxPoolSize)

    def insert(self,dbName,table,data):
        db = self.client[dbName]
        col = db[table]
        col.insert_one(data)

    def query(self,dbName,table,fields =[],where = {}):
        dic = {}
        for field in fields:
            dic[field] = 1
        db = self.client[dbName]
        col = db[table]
        qs = col.find(where,dic)
        return qs 




mongoClient = MongoClientProxy()
mongoClient.host = '127.0.0.1'
mongoClient.port = 27017
mongoClient.conn()



mysqlClient = DataBaseByMysql()
mysqlClient.MIDDLEWARE_NAME = "DATABASE_MIDDLEWARE_BY_PARK"
asyncio.get_event_loop().run_until_complete(mysqlClient.connect())


