#!/usr/bin/env python3
"""
Quick Start: Send Real-Time Earthquake Data to Server
=====================================================

Script ini menunjukkan cara mengirim data gempa real-time dari sensor
ke web dashboard dalam 5 menit.

Requirement:
- Python 3.6+
- requests library: pip install requests

Usage:
    python send_earthquake_data.py
"""

import requests
import json
import time
from datetime import datetime
import random

# ============================================================
# CONFIGURATION - SESUAIKAN DENGAN DEVICE ANDA
# ============================================================

# URL server (ganti dengan IP/domain server Anda)
SERVER_URL = "http://localhost:8000"

# API Key (dapatkan dari registrasi device)
API_KEY = "your_api_key_here"

# Device ID
DEVICE_ID = "SENSOR-001"

# ============================================================


class EarthquakeDataSender:
    """Class untuk mengirim data gempa ke server"""
    
    def __init__(self, server_url, api_key):
        self.server_url = server_url.rstrip('/')
        self.api_key = api_key
        self.endpoint = f"{self.server_url}/api/v1/devices/data"
        self.heartbeat_endpoint = f"{self.server_url}/api/v1/devices/heartbeat"
        
    def send_data(self, data_type, value, timestamp=None):
        """
        Kirim single data point ke server
        
        Args:
            data_type (str): Tipe data (gempa, vibration, acceleration, dll)
            value (int/float/dict): Nilai sensor
            timestamp (str): ISO8601 timestamp (optional)
        
        Returns:
            dict: Response dari server
        """
        
        if timestamp is None:
            timestamp = datetime.utcnow().isoformat() + "Z"
        
        payload = {
            "data": [
                {
                    "type": data_type,
                    "value": value,
                    "timestamp": timestamp
                }
            ]
        }
        
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        try:
            response = requests.post(
                self.endpoint,
                headers=headers,
                json=payload,
                timeout=5
            )
            
            if response.status_code == 200:
                print(f"✅ Data sent: {data_type} = {value}")
                return response.json()
            else:
                print(f"❌ Error {response.status_code}: {response.text}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"❌ Connection error: {e}")
            return None
    
    def send_batch_data(self, data_list):
        """
        Kirim multiple data points sekaligus (lebih efisien)
        
        Args:
            data_list (list): List of {"type": "...", "value": ...}
        
        Returns:
            dict: Response dari server
        """
        
        payload = {"data": data_list}
        
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        try:
            response = requests.post(
                self.endpoint,
                headers=headers,
                json=payload,
                timeout=5
            )
            
            if response.status_code == 200:
                print(f"✅ Batch sent: {len(data_list)} data points")
                return response.json()
            else:
                print(f"❌ Error {response.status_code}: {response.text}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"❌ Connection error: {e}")
            return None
    
    def send_heartbeat(self, metadata=None):
        """
        Kirim heartbeat untuk keep-alive
        
        Args:
            metadata (dict): Optional device metadata
        """
        
        headers = {
            "X-API-Key": self.api_key,
            "Content-Type": "application/json"
        }
        
        data = {}
        if metadata:
            data["metadata"] = metadata
        
        try:
            response = requests.post(
                self.heartbeat_endpoint,
                headers=headers,
                json=data,
                timeout=5
            )
            
            if response.status_code == 200:
                print(f"💓 Heartbeat sent")
                return True
            else:
                print(f"❌ Heartbeat failed: {response.status_code}")
                return False
                
        except requests.exceptions.RequestException as e:
            print(f"❌ Heartbeat error: {e}")
            return False


# ============================================================
# CONTOH PENGGUNAAN
# ============================================================

def example_1_simple_send():
    """Contoh 1: Kirim data sederhana"""
    print("\n📝 Contoh 1: Kirim Data Sederhana")
    print("=" * 50)
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    # Kirim intensity data
    sender.send_data("gempa", 250)
    
    # Kirim vibration data
    sender.send_data("vibration", 120)


def example_2_complex_value():
    """Contoh 2: Kirim data complex (object)"""
    print("\n📝 Contoh 2: Kirim Data Complex")
    print("=" * 50)
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    # Kirim earthquake dengan detail
    earthquake_data = {
        "intensitas": 350,
        "magnitude": 6.5,
        "kedalaman": 15,
        "latitude": -6.2,
        "longitude": 106.8
    }
    
    sender.send_data("gempa", earthquake_data)


def example_3_batch_send():
    """Contoh 3: Kirim multiple data sekaligus"""
    print("\n📝 Contoh 3: Batch Send (Multiple Data)")
    print("=" * 50)
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    batch_data = [
        {
            "type": "gempa",
            "value": 250,
            "timestamp": datetime.utcnow().isoformat() + "Z"
        },
        {
            "type": "vibration",
            "value": 120,
            "timestamp": datetime.utcnow().isoformat() + "Z"
        },
        {
            "type": "temperature",
            "value": 35.5,
            "timestamp": datetime.utcnow().isoformat() + "Z"
        }
    ]
    
    sender.send_batch_data(batch_data)


def example_4_continuous_stream():
    """Contoh 4: Simulasi sensor real-time stream"""
    print("\n📝 Contoh 4: Continuous Real-Time Stream")
    print("=" * 50)
    print("Sending data setiap 2 detik. Press Ctrl+C untuk stop.\n")
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    try:
        iteration = 0
        while True:
            # Simulate earthquake data
            intensity = random.randint(50, 500)
            
            # Send earthquake data
            sender.send_data("gempa", intensity)
            
            # Send heartbeat setiap 10 kali (20 detik)
            iteration += 1
            if iteration % 10 == 0:
                sender.send_heartbeat({
                    "uptime": iteration * 2,
                    "cpu_temp": random.uniform(40, 60)
                })
            
            time.sleep(2)  # Wait 2 seconds
            
    except KeyboardInterrupt:
        print("\n\n✋ Stopped by user")


def example_5_from_real_sensor():
    """Contoh 5: Template untuk membaca dari real sensor"""
    print("\n📝 Contoh 5: Template dari Real Sensor")
    print("=" * 50)
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    # Template untuk integrate dengan real sensor
    # Ganti get_sensor_reading() dengan code yang sebenarnya
    
    def get_sensor_reading():
        """Baca dari sensor hardware"""
        # GANTI INI dengan actual sensor reading code
        # Contoh menggunakan I2C, SPI, atau GPIO
        return {
            "intensitas": random.randint(100, 500),
            "magnitude": random.uniform(2, 8),
            "kedalaman": random.randint(5, 100)
        }
    
    # Baca dan kirim data
    sensor_data = get_sensor_reading()
    sender.send_data("gempa", sensor_data)


def example_6_with_error_handling():
    """Contoh 6: Error handling yang proper"""
    print("\n📝 Contoh 6: Error Handling")
    print("=" * 50)
    
    sender = EarthquakeDataSender(SERVER_URL, API_KEY)
    
    try:
        # Kirim data
        response = sender.send_data("gempa", 250)
        
        if response and response.get('success'):
            print("✅ Data berhasil dikirim")
            print(f"   Device status: {response.get('device_status')}")
            print(f"   Count: {response.get('count')}")
        else:
            print("❌ Gagal kirim data")
            print(f"   Response: {response}")
            
    except Exception as e:
        print(f"❌ Error: {e}")


# ============================================================
# MAIN
# ============================================================

if __name__ == "__main__":
    print("""
╔════════════════════════════════════════════════════════════╗
║    📡 Earthquake Real-Time Data Sender                     ║
║                                                            ║
║    Contoh Script Mengirim Data Gempa ke Dashboard         ║
╚════════════════════════════════════════════════════════════╝
    """)
    
    # Print configuration
    print(f"Server URL: {SERVER_URL}")
    print(f"API Key: {API_KEY[:10]}...")
    print(f"Device ID: {DEVICE_ID}")
    print()
    
    # Pilih contoh
    print("Pilih contoh yang ingin dijalankan:")
    print("1. Kirim data sederhana")
    print("2. Kirim data complex (object)")
    print("3. Batch send (multiple data)")
    print("4. Continuous real-time stream (simulasi)")
    print("5. Template dari real sensor")
    print("6. Error handling")
    print("0. Exit")
    print()
    
    choice = input("Pilih (0-6): ").strip()
    
    if choice == "1":
        example_1_simple_send()
    elif choice == "2":
        example_2_complex_value()
    elif choice == "3":
        example_3_batch_send()
    elif choice == "4":
        example_4_continuous_stream()
    elif choice == "5":
        example_5_from_real_sensor()
    elif choice == "6":
        example_6_with_error_handling()
    elif choice == "0":
        print("Bye!")
    else:
        print("❌ Invalid choice")
        
    print("\n✅ Done!")
