#!/usr/bin/env python3
"""
Flask LED and Buzzer Control Application for reTerminal DM4
Provides REST API for controlling both the LED and buzzer
"""

from flask import Flask, jsonify, request
import subprocess
import time
import threading

app = Flask(__name__)
LED_PATH = '/sys/class/leds/usr-led/brightness'
BUZZER_PATH = '/sys/class/leds/usr-buzzer/brightness'

class LEDController:
    """LED controller class"""
    
    def __init__(self):
        self.is_active = False
        self.thread = None
    
    def _write(self, value):
        """Internal method to write to LED"""
        try:
            subprocess.run(['sudo', 'tee', LED_PATH], 
                          input=str(value), text=True, 
                          stdout=subprocess.DEVNULL, 
                          stderr=subprocess.DEVNULL,
                          check=True)
            return True
        except subprocess.CalledProcessError:
            return False
    
    def on(self):
        """Turn LED ON"""
        return self._write(1)
    
    def off(self):
        """Turn LED OFF"""
        return self._write(0)
    
    def toggle(self):
        """Toggle LED state"""
        try:
            result = subprocess.run(['cat', LED_PATH], 
                                 capture_output=True, text=True, check=True)
            current = result.stdout.strip()
            new_state = '0' if current == '1' else '1'
            return self._write(new_state)
        except:
            return False
    
    def blink(self, count=5, on_time=0.2, off_time=0.2):
        """Blink LED specified number of times"""
        if self.is_active:
            return False
        
        def _blink():
            self.is_active = True
            for _ in range(count):
                self.on()
                time.sleep(on_time)
                self.off()
                time.sleep(off_time)
            self.is_active = False
        
        self.thread = threading.Thread(target=_blink, daemon=True)
        self.thread.start()
        return True
    
    def pulse(self, duration=2, interval=0.1):
        """Pulse LED for specified duration"""
        if self.is_active:
            return False
        
        def _pulse():
            self.is_active = True
            end_time = time.time() + duration
            while time.time() < end_time:
                self.on()
                time.sleep(interval)
                self.off()
                time.sleep(interval)
            self.is_active = False
        
        self.thread = threading.Thread(target=_pulse, daemon=True)
        self.thread.start()
        return True
    
    def status(self):
        """Get LED status"""
        try:
            result = subprocess.run(['cat', LED_PATH], 
                                  capture_output=True, text=True, check=True)
            state = result.stdout.strip()
            return 'ON' if state == '1' else 'OFF'
        except:
            return 'UNKNOWN'

class BuzzerController:
    """Buzzer controller class"""
    
    def __init__(self):
        self.is_playing = False
        self.play_thread = None
    
    def _write(self, value):
        """Internal method to write to buzzer"""
        try:
            subprocess.run(['sudo', 'tee', BUZZER_PATH], 
                          input=str(value), text=True, 
                          stdout=subprocess.DEVNULL, 
                          stderr=subprocess.DEVNULL,
                          check=True)
            return True
        except subprocess.CalledProcessError:
            return False
    
    def on(self):
        """Turn buzzer ON"""
        return self._write(1)
    
    def off(self):
        """Turn buzzer OFF"""
        return self._write(0)
    
    def beep(self, duration=0.2):
        """Play a single beep"""
        self.on()
        time.sleep(duration)
        self.off()
    
    def play_pattern(self, pattern):
        """Play a pattern"""
        if self.is_playing:
            return False
        
        def _play():
            self.is_playing = True
            for on_time, off_time in pattern:
                self.on()
                time.sleep(on_time)
                self.off()
                time.sleep(off_time)
            self.is_playing = False
        
        self.play_thread = threading.Thread(target=_play, daemon=True)
        self.play_thread.start()
        return True
    
    def status(self):
        """Get buzzer status"""
        try:
            result = subprocess.run(['cat', BUZZER_PATH], 
                                  capture_output=True, text=True, check=True)
            state = result.stdout.strip()
            return 'ON' if state == '1' else 'OFF'
        except:
            return 'UNKNOWN'

# Create global controllers
led = LEDController()
buzzer = BuzzerController()

@app.route('/')
def index():
    """API documentation endpoint"""
    return jsonify({
        'status': 'LED and Buzzer Control API',
        'version': '1.0',
        'endpoints': {
            'LED': {
                '/led/on': 'Turn LED ON (POST, GET)',
                '/led/off': 'Turn LED OFF (POST, GET)',
                '/led/toggle': 'Toggle LED (POST, GET)',
                '/led/blink': 'Blink LED (GET: ?count=5&on_time=0.2&off_time=0.2)',
                '/led/pulse': 'Pulse LED (GET: ?duration=2&interval=0.1)',
                '/led/status': 'Get LED status (GET)'
            },
            'Buzzer': {
                '/buzzer/on': 'Turn buzzer ON (POST, GET)',
                '/buzzer/off': 'Turn buzzer OFF (POST, GET)',
                '/buzzer/beep': 'Play beep (GET: ?duration=0.2)',
                '/buzzer/status': 'Get buzzer status (GET)'
            },
            'Combined': {
                '/alert': 'Alert with LED and buzzer (GET: ?type=info|success|error|warning)'
            }
        }
    })

# LED Endpoints
@app.route('/led/on', methods=['POST', 'GET'])
def led_on():
    """Turn LED ON"""
    if led.on():
        return jsonify({'status': 'success', 'message': 'LED turned ON'})
    return jsonify({'status': 'error', 'message': 'Failed to turn LED ON'}), 500

@app.route('/led/off', methods=['POST', 'GET'])
def led_off():
    """Turn LED OFF"""
    if led.off():
        return jsonify({'status': 'success', 'message': 'LED turned OFF'})
    return jsonify({'status': 'error', 'message': 'Failed to turn LED OFF'}), 500

@app.route('/led/toggle', methods=['POST', 'GET'])
def led_toggle():
    """Toggle LED state"""
    if led.toggle():
        return jsonify({'status': 'success', 'message': 'LED toggled'})
    return jsonify({'status': 'error', 'message': 'Failed to toggle LED'}), 500

@app.route('/led/blink', methods=['POST', 'GET'])
def led_blink():
    """Blink LED"""
    count = int(request.args.get('count', 5))
    on_time = float(request.args.get('on_time', 0.2))
    off_time = float(request.args.get('off_time', 0.2))
    
    if led.blink(count, on_time, off_time):
        return jsonify({
            'status': 'success', 
            'message': f'LED blinking {count} times'
        })
    return jsonify({
        'status': 'error', 
        'message': 'LED is already active'
    }), 409

@app.route('/led/pulse', methods=['POST', 'GET'])
def led_pulse():
    """Pulse LED"""
    duration = float(request.args.get('duration', 2))
    interval = float(request.args.get('interval', 0.1))
    
    if led.pulse(duration, interval):
        return jsonify({
            'status': 'success', 
            'message': f'LED pulsing for {duration} seconds'
        })
    return jsonify({
        'status': 'error', 
        'message': 'LED is already active'
    }), 409

@app.route('/led/status', methods=['GET'])
def led_status():
    """Get LED status"""
    state = led.status()
    return jsonify({
        'status': 'success',
        'led': state,
        'is_active': led.is_active
    })

# Buzzer Endpoints
@app.route('/buzzer/on', methods=['POST', 'GET'])
def buzzer_on():
    """Turn buzzer ON"""
    if buzzer.on():
        return jsonify({'status': 'success', 'message': 'Buzzer turned ON'})
    return jsonify({'status': 'error', 'message': 'Failed to turn buzzer ON'}), 500

@app.route('/buzzer/off', methods=['POST', 'GET'])
def buzzer_off():
    """Turn buzzer OFF"""
    if buzzer.off():
        return jsonify({'status': 'success', 'message': 'Buzzer turned OFF'})
    return jsonify({'status': 'error', 'message': 'Failed to turn buzzer OFF'}), 500

@app.route('/buzzer/beep', methods=['POST', 'GET'])
def buzzer_beep():
    """Play a beep"""
    duration = float(request.args.get('duration', 0.2))
    if duration < 0 or duration > 5:
        return jsonify({
            'status': 'error', 
            'message': 'Duration must be between 0 and 5 seconds'
        }), 400
    
    buzzer.beep(duration)
    return jsonify({
        'status': 'success', 
        'message': f'Beeped for {duration} seconds'
    })

@app.route('/buzzer/status', methods=['GET'])
def buzzer_status():
    """Get buzzer status"""
    state = buzzer.status()
    return jsonify({
        'status': 'success',
        'buzzer': state,
        'is_playing': buzzer.is_playing
    })

# Combined Alert Endpoint
@app.route('/alert', methods=['GET'])
def alert():
    """Alert with LED and buzzer"""
    alert_type = request.args.get('type', 'info')
    
    patterns = {
        'info': {
            'led': (1, 0.2, 0.2),      # 1 blink
            'buzzer': (0.1, 0.1)        # Short beep
        },
        'success': {
            'led': (2, 0.1, 0.1),      # 2 fast blinks
            'buzzer': (0.2, 0.1)        # Medium beep
        },
        'warning': {
            'led': (2, 0.3, 0.3),      # 2 slow blinks
            'buzzer': (0.3, 0.2)        # Longer beep
        },
        'error': {
            'led': (3, 0.05, 0.05),    # 3 very fast blinks
            'buzzer': (0.2, 0.05)       # Fast beeps
        }
    }
    
    if alert_type not in patterns:
        return jsonify({
            'status': 'error', 
            'message': 'Invalid alert type. Use: info, success, warning, error'
        }), 400
    
    pattern = patterns[alert_type]
    
    # Start LED blink
    count, on_time, off_time = pattern['led']
    led.blink(count, on_time, off_time)
    
    # Play buzzer pattern
    beep_duration, pause = pattern['buzzer']
    buzzer_pattern = [(beep_duration, pause)] * count
    buzzer.play_pattern(buzzer_pattern)
    
    return jsonify({
        'status': 'success', 
        'message': f'Alert ({alert_type}) triggered'
    })

if __name__ == '__main__':
    print("Starting LED and Buzzer Control API...")
    print("API available at http://0.0.0.0:5000")
    print("Documentation at http://0.0.0.0:5000/")
    app.run(host='0.0.0.0', port=5000, debug=True)
