from flask import Flask
import cv2
import mediapipe as mp
import threading
import time
import sys

app = Flask(__name__)
latest_gesture = 0
gesture_lock = threading.Lock()

GESTURE_NONE = 0
GESTURE_BUY = 1
GESTURE_SELL = 2
GESTURE_CLOSE_ALL = 3

mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)

# Open camera
cap = None
for backend in [cv2.CAP_DSHOW, cv2.CAP_ANY]:
    cap = cv2.VideoCapture(0, backend)
    if cap.isOpened():
        print(f"Camera opened with backend {backend}")
        break
    cap.release()

if cap is None or not cap.isOpened():
    print("ERROR: Cannot open webcam.")
    sys.exit(1)

def classify_gesture(landmarks):
    wrist = landmarks.landmark[0]
    thumb_tip = landmarks.landmark[4]
    thumb_mcp = landmarks.landmark[2]
    index_tip = landmarks.landmark[8]
    index_mcp = landmarks.landmark[5]
    middle_tip = landmarks.landmark[12]
    middle_mcp = landmarks.landmark[9]
    ring_tip = landmarks.landmark[16]
    ring_mcp = landmarks.landmark[13]
    pinky_tip = landmarks.landmark[20]
    pinky_mcp = landmarks.landmark[17]

    def dist(a, b):
        dx = a.x - b.x
        dy = a.y - b.y
        dz = a.z - b.z
        return (dx*dx + dy*dy + dz*dz) ** 0.5

    hand_size = dist(wrist, middle_mcp)
    if hand_size < 1e-6:
        hand_size = 1.0

    thumb_curl = dist(thumb_tip, thumb_mcp) / hand_size
    index_curl = dist(index_tip, index_mcp) / hand_size
    middle_curl = dist(middle_tip, middle_mcp) / hand_size
    ring_curl = dist(ring_tip, ring_mcp) / hand_size
    pinky_curl = dist(pinky_tip, pinky_mcp) / hand_size

    # Debug: print curl values (uncomment if needed)
    # print(f"curls: t={thumb_curl:.2f} i={index_curl:.2f} m={middle_curl:.2f} r={ring_curl:.2f} p={pinky_curl:.2f}")

    thumb_up = (thumb_curl > 0.7 and index_curl < 0.4 and middle_curl < 0.4 and 
                ring_curl < 0.4 and pinky_curl < 0.4 and thumb_tip.y < wrist.y)

    pointing = (index_curl > 0.8 and middle_curl < 0.4 and ring_curl < 0.4 and 
                pinky_curl < 0.4 and thumb_curl < 0.6)

    fist = (index_curl < 0.5 and middle_curl < 0.5 and ring_curl < 0.5 and 
            pinky_curl < 0.5 and thumb_curl < 0.6)

    if fist:
        return GESTURE_CLOSE_ALL
    elif thumb_up:
        return GESTURE_SELL
    elif pointing:
        return GESTURE_BUY
    return GESTURE_NONE

def gesture_loop():
    global latest_gesture
    last = GESTURE_NONE
    print("Gesture detection started. Show your hand.")
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            time.sleep(0.1)
            continue
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        result = hands.process(rgb)
        gesture = GESTURE_NONE
        if result.multi_hand_landmarks:
            gesture = classify_gesture(result.multi_hand_landmarks[0])
            mp.solutions.drawing_utils.draw_landmarks(
                frame, result.multi_hand_landmarks[0], mp_hands.HAND_CONNECTIONS)
        if gesture != last:
            with gesture_lock:
                latest_gesture = gesture
            print(f"Gesture: {gesture}")
            last = gesture
        cv2.imshow("Gesture Control", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    hands.close()

@app.route('/command', methods=['GET'])
def get_command():
    global latest_gesture
    with gesture_lock:
        code = latest_gesture
        latest_gesture = 0
    return str(code), 200

if __name__ == '__main__':
    t = threading.Thread(target=gesture_loop, daemon=True)
    t.start()
    print("HTTP server running on http://127.0.0.1:8080")
    app.run(host='127.0.0.1', port=8080, threaded=False)