import json
from pathlib import Path
import sqlite3
import threading
import time
import atexit


def init_logdb():
    conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False, cached_statements=2048)
    cursor = conn.cursor()
    cursor.execute("PRAGMA journal_mode=wal")
    cursor.execute("PRAGMA wal_checkpoint=TRUNCATE")
    cursor.execute("PRAGMA synchronous=normal")
    cursor.execute("PRAGMA temp_store=memory")
    cursor.execute("PRAGMA mmap_size=30000000000")
    cursor.execute("PRAGMA cache_size=200000")
    cursor.execute(
        """
        create table if not exists logs(
            id integer primary key autoincrement,
            timestamp DATETIME DEFAULT(STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')),
            level text,
            module text,
            content text
        )
        """
    )
    return conn, cursor


def db_lock(func):
    def wrapper(*args, **kwargs):
        try:
            lock.acquire(True)
            ret = func(*args, **kwargs)
        finally:
            lock.release()
        return ret
    return wrapper


def detect_db_size():
    @db_lock
    def release_memory():
        line_number = 20000
        leftover = 4000  # 200s
        cursor.execute("SELECT COUNT(id) FROM logs")
        len_records = cursor.fetchone()[0]
        if len_records > line_number:
            del_num = len_records - leftover + 1
            cursor.execute(f"DELETE FROM logs WHERE id < {del_num}")
            cursor.execute(f"UPDATE logs SET id=(id-{del_num - 1}) WHERE id > {del_num - 1}")
            cursor.execute(f"UPDATE sqlite_sequence SET seq = {leftover + 1} WHERE name = 'logs' ")
            cursor.execute("VACUUM")

    while True:
        release_memory()
        time.sleep(interval*30)


@db_lock
def to_logdb(level="", module="", content=""):
    if "move.monitor" in content:
        return
    cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level.upper(), module, content))


def save_logdb():
    db_file = str(Path.home()) + "\\Downloads\\aio.db"
    disk_db = sqlite3.connect(db_file)
    conn.backup(disk_db)
    disk_db.close()
    conn.close()


# ===========================================================================
base_path = Path(__file__).parent.parent
with open(f"{base_path}/assets/confs/configs.json", mode="r", encoding="utf-8") as f_cfg:
    cfg = json.load(f_cfg)
    ip_addr = cfg["ip_addr"]
    ssh_port = cfg["ssh_port"]
    socket_port = cfg["socket_port"]
    xService_port = cfg["xService_port"]
    external_port = cfg["external_port"]
    modbus_port = cfg["modbus_port"]
    upgrade_port = cfg["upgrade_port"]
    interval = cfg["interval"]
    max_frame_size = cfg["max_frame_size"]
    MAX_RECEIVED_SIZE = cfg["MAX_RECEIVED_SIZE"]
    suffix = cfg["suffix"]
    username = cfg["username"]
    password = cfg["password"]
    retry_time = cfg["retry_time"]

lock = threading.Lock()
conn, cursor = init_logdb()
atexit.register(save_logdb)
t = threading.Thread(target=detect_db_size)
t.daemon = True
t.start()
