from flask import Flask, render_template, Response, request
import cv2
import json
import time
import threading
import mysql.connector
from mysql.connector import Error

app = Flask(__name__)

# Cấu hình kết nối MySQL
db_config = {
    'host': 'localhost',        # Thay bằng host của bạn
    'user': 'root',    # Thay bằng username MySQL
    'password': 'ROOT',# Thay bằng password MySQL
    'database': 'can' # Thay bằng tên database
}

# Hàm lấy camera_urls từ MySQL
def fetch_camera_urls():
    try:
        connection = mysql.connector.connect(**db_config)
        if connection.is_connected():
            cursor = connection.cursor(dictionary=True)
            cursor.execute("SELECT camera_id, rtsp_url FROM cameras")
            rows = cursor.fetchall()
            camera_urls = {row['camera_id']: row['rtsp_url'] for row in rows}
            return camera_urls
    except Error as e:
        print(f"Lỗi kết nối MySQL: {e}")
        return {}
    finally:
        if 'cursor' in locals():
            cursor.close()
        if 'connection' in locals() and connection.is_connected():
            connection.close()

# Khởi tạo biến toàn cục
camera_urls = fetch_camera_urls()  # Lấy dữ liệu từ MySQL khi khởi động
camera_client_counts = {}
camera_threads = {}
camera_frames = {}

# Hàm xóa cache camera
def clear_camera_cache(camera_id):
    if camera_id in camera_frames:
        del camera_frames[camera_id]
        print(f"Đã xóa cache cho camera {camera_id}")

# Hàm tạo frame từ RTSP
def generate_frames(rtsp_url, camera_id, interval=0.1):
    cap = cv2.VideoCapture(rtsp_url)
    cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)  # Thiết lập kích thước buffer

    if not cap.isOpened():
        print(f"Không thể kết nối với {rtsp_url}. Đang thử lại sau 5 giây...")
        cap.release()
        time.sleep(5)
        return

    last_frame_time = time.time()

    while True:
        success, frame = cap.read()
        if not success:
            print(f"Mất kết nối với {rtsp_url}. Đang thử lại...")
            cap.release()
            time.sleep(5)
            cap = cv2.VideoCapture(rtsp_url)
            continue

        current_time = time.time()
        elapsed_time = current_time - last_frame_time
        frame = cv2.resize(frame, (640, 320))  # Giảm độ phân giải
        if elapsed_time >= interval:
            last_frame_time = current_time
            _, buffer = cv2.imencode('.jpg', frame)
            frame = buffer.tobytes()
            camera_frames[camera_id] = frame

        time.sleep(0.01)

    cap.release()

@app.route('/')
def index():
    camera_ids = request.args.getlist('id')  # Lấy danh sách id camera từ query string
    return render_template('index.html', camera_ids_json=json.dumps(camera_ids))

@app.route('/video_feed')
def video_feed():
    camera_id = request.args.get('id', default='581FG06', type=str)
    rtsp_url = camera_urls.get(camera_id, '')  # Lấy URL từ dictionary đã tải từ MySQL

    if rtsp_url:
        if camera_id not in camera_threads:
            thread = threading.Thread(target=generate_frames, args=(rtsp_url, camera_id))
            thread.daemon = True
            thread.start()
            camera_threads[camera_id] = thread
        if camera_id in camera_client_counts:
            camera_client_counts[camera_id] += 1
        else:
            camera_client_counts[camera_id] = 1

        def generate_response():
            while True:
                frame = camera_frames.get(camera_id)
                if frame:
                    yield (b'--frame\r\n'
                           b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
                time.sleep(0.1)

        def cleanup_client():
            if camera_id in camera_client_counts:
                camera_client_counts[camera_id] -= 1
                if camera_client_counts[camera_id] == 0:
                    clear_camera_cache(camera_id)
                    del camera_client_counts[camera_id]

        response = Response(generate_response(), mimetype='multipart/x-mixed-replace; boundary=frame')
        response.call_on_close(cleanup_client)
        return response
    else:
        return "Camera không tồn tại", 404

# Cập nhật camera_urls định kỳ (tùy chọn)
def update_camera_urls_periodically():
    global camera_urls
    while True:
        camera_urls = fetch_camera_urls()
        print("Đã cập nhật camera_urls từ MySQL")
        time.sleep(300)  # Cập nhật mỗi 5 phút

if __name__ == "__main__":
    # Khởi động luồng cập nhật camera_urls (tùy chọn)
    update_thread = threading.Thread(target=update_camera_urls_periodically, daemon=True)
    update_thread.start()

    # Chạy Flask với Waitress
    from waitress import serve
    serve(app, host='0.0.0.0', port=5000, threads=16)