import sys
import os
import serial
import time
import subprocess
import shutil
import requests
import base64
from datetime import datetime

SERIAL_PORT = "/dev/ttyUSB2"
PHONE_NUMBER = "+11234567890" # replace with phone number in international format
PHOTO_INTERVAL = 5
SMS_INTERVAL = 60
CAPTURE_PATH = "/home/pi/captures/latest_photo.jpg" # replace directory name but not file name

def print_flush(text):
    print(text)
    sys.stdout.flush()

def take_photo():
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    photo_name = f"/home/pi/captures/photo_{timestamp}.jpg"
    print_flush(f"Capturing photo: {photo_name}")

    try:
        subprocess.run(["rpicam-still", "-o", photo_name, "--immediate", "--nopreview"], check=True)

        latest_path = "/home/pi/captures/latest.jpg"
        if os.path.lexists(latest_path):
            os.remove(latest_path)
        os.symlink(photo_name, latest_path)
        return photo_name
    except Exception as e:
        print_flush(f"Camera Error {e}")
        return None


def upload_to_imgbb():
    api_key = "replace with your 32-digit API key from ImgBB"
    try:
        with open("/home/pi/captures/latest.jpg", "rb") as file:
            img_data = base64.b64encode(file.read())
        payload = {
            "key": api_key,
            "image": img_data,
        }
        response = requests.post("https://api.imgbb.com/1/upload", data=payload)
        response_data = response.json()

        if response_data['success']:
            return response_data['data']['url']
        else:
            print_flush(f"ImgBB Error: {response_data['error']['message']}")
            return None
    except Exception as e:
        print_flush(f"Failed to connect to ImgBB:{e}")
        return None

def convert_to_decimal(coord, direction):
    if not coord or coord == '':
        return 0.0
    dot_index = coord.find('.')
    degrees = float(coord[:dot_index - 2])
    minutes = float(coord[dot_index - 2:])
    decimal = degrees + (minutes / 60)
    if direction in ['S', 'W']:
        decimal = -decimal
    return round(decimal, 6)

def get_location_link(ser):
    ser.write(b'AT+CGPS=1\r\n')
    time.sleep(2)

    ser.write(b'AT+CGPSINFO\r\n')
    time.sleep(1)
    response = ser.read_all().decode(errors='ignore')

    if "+CGPSINFO:" in response:
        raw_data = response.split("+CGPSINFO:")[1].split('\r')[0].strip()

        if ",,,," in raw_data or raw_data == "":
            return "GPS is still searching for satellite fix"

        parts = raw_data.split(',')
        lat_dd = convert_to_decimal(parts[0], parts[1])
        lon_dd = convert_to_decimal(parts[2], parts[3])
        alt = parts[6]
        return f" Alt: {alt}m | Pi Location: https://www.google.com/maps?q={lat_dd},{lon_dd}"

    return "Error: Could not communicate with GPS engine"

def send_sms(img_link):
    try:
        with serial.Serial(SERIAL_PORT, 115200, timeout=5) as ser:
            gps_link = get_location_link(ser)
            ser.write(b'AT+CNMP=38\r\n')
            time.sleep(1)
            ser.write(b'AT+CSMP=17,167,0,0\r\n')
            time.sleep(1)
            ser.write(b'AT+CSCS="GSM"\r\n')
            time.sleep(1)

            timestamp = datetime.now().strftime("%H:%M")
            final_msg = f"[{timestamp}] Loc: {gps_link} \nPhoto: {img_link if img_link else 'Upload Failed.'}"

            ser.write(b'AT+CMGF=1\r\n')
            time.sleep(1)
            ser.write(b'AT+CSCS="GSM"\r\n')
            time.sleep(1)
            ser.write(f'AT+CMGS="{PHONE_NUMBER}"\r\n'.encode())
            time.sleep(1)
            ser.write(final_msg.encode() + b'\x1a')
            print_flush(f"Sent: {final_msg}")

    except Exception as e:
        print_flush(f"Error: {e}")

def main_loop():
    print_flush(f"Starting Tracker and Camera. Interval: {SMS_INTERVAL}s")
    last_sms_time = time.time()
    while True:
        loop_start = time.time()
        take_photo()
        current_time = time.time()
        if (current_time - last_sms_time) >= SMS_INTERVAL:
            print_flush("Interval reached. Preparing SMS report...")
            img_url = upload_to_imgbb()
            send_sms(img_url)
            last_sms_time = current_time

        elapsed = time.time() - loop_start
        sleep_time = max(0, PHOTO_INTERVAL - elapsed)
        time.sleep(sleep_time)


if __name__ == "__main__":
    main_loop()

