import os
import struct
import math
import numpy as np
import argparse
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import sys
import io
import traceback
import binascii

VERSION = "1.1.0"

class AITrackPoint:
    def __init__(self, x=0, y=0, z=0, dx=0, dy=0, dz=0, turn_brake=0, placeholder=None):
        self.x = x
        self.y = y  
        self.z = z
        self.dx = dx
        self.dy = dy
        self.dz = dz
        self.turn_brake = turn_brake
        self.placeholder = 0 if placeholder is None else placeholder
        
    @classmethod
    def from_csv_line(cls, line):
        """Create point from a CSV line"""
        # Handle various CSV formats
        if isinstance(line, str):
            # Split by comma and handle both comma and comma+space separators
            values = [float(v.strip()) for v in line.strip().split(',')]
        elif isinstance(line, list):
            # Already a list of values
            values = line
        else:
            return None
        
        if len(values) >= 7:
            return cls(
                x=values[0], y=values[1], z=values[2],
                dx=values[3], dy=values[4], dz=values[5],
                turn_brake=values[6],
                placeholder=values[7] if len(values) > 7 else 0
            )
        return None
    
    def to_csv_line(self, separator=', '):
        """Convert point to CSV line format"""
        return f"{self.x}{separator}{self.y}{separator}{self.z}{separator}{self.dx}{separator}{self.dy}{separator}{self.dz}{separator}{self.turn_brake}{separator}{self.placeholder}"
    
    def calculate_speed_and_turn(self):
        """Calculate speed and turn values from the encoded turn_brake parameter"""
        # Handle special case of gentle turn at full speed
        if -2.0 <= self.turn_brake <= 1.0:
            return 1.0, self.turn_brake
        
        # Regular calculation
        turn_strength = self.turn_brake % 1.0
        if abs(turn_strength) < 0.001:  # Handle small floating point errors
            turn_strength = 0.0
            
        max_speed = 1.0 - (self.turn_brake - turn_strength) / 40.0
        
        # Validate and clamp
        max_speed = max(0.2, min(1.0, max_speed))
        turn_strength = max(-2.0, min(1.0, turn_strength))
        
        return max_speed, turn_strength
    
    def set_speed_and_turn(self, max_speed, turn_strength):
        """Set the turn_brake parameter based on speed and turn values"""
        # Validate inputs
        max_speed = max(0.2, min(1.0, max_speed))
        turn_strength = max(-2.0, min(1.0, turn_strength))
            
        # Calculate combined value
        self.turn_brake = 40.0 * (1.0 - max_speed) + turn_strength
        
    def __str__(self):
        max_speed, turn_strength = self.calculate_speed_and_turn()
        return (f"Point({self.x:.2f}, {self.y:.2f}, {self.z:.2f}) - "
                f"Direction({self.dx:.2f}, {self.dy:.2f}, {self.dz:.2f}) - "
                f"Speed: {max_speed:.2f}, Turn: {turn_strength:.2f}")


class AITrackPath:
    def __init__(self, points=None):
        self.points = points or []
        self.debug = False
        
    def set_debug(self, debug):
        self.debug = debug
        
    def log_debug(self, message):
        if self.debug:
            print(f"[DEBUG] {message}")
    
    @staticmethod
    def detect_file_type(filename):
        """Detect file type based on content and/or filename"""
        # Try to detect by extension first
        _, ext = os.path.splitext(filename)
        if ext:
            ext = ext.lower()
            if ext == '.csv':
                return 'csv'
            elif ext in ['.rec', '.bin']:
                return 'rec'
            elif ext == '.obj':
                return 'obj'
            elif ext == '.dxf':
                return 'dxf'
        
        # If no extension or unknown extension, try to detect by content
        try:
            with open(filename, 'rb') as f:
                first_bytes = f.read(100)  # Read first 100 bytes
                
                # Check if it's a text file
                try:
                    text = first_bytes.decode('utf-8')
                    
                    # Check for CSV (first line might be a number or have commas)
                    if text.strip().isdigit() or ',' in text:
                        return 'csv'
                    
                    # Check for OBJ (should start with comments or 'v')
                    if text.startswith('#') or text.startswith('v '):
                        return 'obj'
                    
                    # Check for DXF (should start with '0' and 'SECTION')
                    if '0\nSECTION' in text or '0\r\nSECTION' in text:
                        return 'dxf'
                    
                except UnicodeDecodeError:
                    # Not a text file, likely binary
                    # Try to interpret as REC file
                    return 'rec'
        except Exception as e:
            print(f"Error detecting file type: {str(e)}")
            
        # Default to REC for files with no extension and unknown content
        if not ext:
            return 'rec'
            
        return None
        
    @classmethod
    def from_csv(cls, filename, debug=False):
        """Load track from CSV file"""
        path = cls()
        path.set_debug(debug)
        
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                lines = f.readlines()
                
            path.log_debug(f"Read {len(lines)} lines from CSV file")
            
            # Check if first line is number of points
            first_line = lines[0].strip()
            start_line = 1
            num_points = None
            
            try:
                # Try to parse first line as number of points
                num_points = int(first_line)
                path.log_debug(f"First line indicates {num_points} points")
            except ValueError:
                # First line might be a header or the first point
                if ',' in first_line:
                    # Probably a point, not a header
                    start_line = 0
                    num_points = len(lines)
                    path.log_debug("First line appears to be a point, not a count")
                else:
                    # Probably a header, skip it
                    start_line = 1
                    num_points = len(lines) - 1
                    path.log_debug("First line appears to be a header, skipping")
            
            # Read each point
            for i in range(start_line, len(lines)):
                line = lines[i].strip()
                if not line:  # Skip empty lines
                    continue
                    
                point = AITrackPoint.from_csv_line(line)
                if point:
                    path.points.append(point)
                else:
                    path.log_debug(f"Failed to parse line {i+1}: {line}")
                
            path.log_debug(f"Successfully parsed {len(path.points)} points")
            
        except Exception as e:
            print(f"Error reading CSV file: {str(e)}")
            traceback.print_exc()
                
        return path
    
    @classmethod
    def from_binary(cls, filename, debug=False):
        """Load track from binary REC file"""
        path = cls()
        path.set_debug(debug)
        
        try:
            with open(filename, 'rb') as f:
                file_data = f.read()
                
            path.log_debug(f"File size: {len(file_data)} bytes")
            
            if debug:
                # Print first few bytes for debugging
                hex_data = binascii.hexlify(file_data[:64]).decode('ascii')
                path.log_debug(f"First 64 bytes (hex): {hex_data}")
            
            # Try to detect if the file has a header with point count
            has_header = False
            num_points = None
            offset = 0
            
            # Try using the first 4 bytes as an integer point count
            if len(file_data) >= 4:
                try:
                    # Try little endian
                    num_points_le = struct.unpack('<i', file_data[:4])[0]
                    
                    # Try big endian
                    num_points_be = struct.unpack('>i', file_data[:4])[0]
                    
                    # Use the one that makes more sense
                    if 0 < num_points_le < 10000:
                        num_points = num_points_le
                        has_header = True
                        offset = 4
                        path.log_debug(f"Detected point count header (LE): {num_points}")
                    elif 0 < num_points_be < 10000:
                        num_points = num_points_be
                        has_header = True
                        offset = 4
                        path.log_debug(f"Detected point count header (BE): {num_points}")
                    else:
                        path.log_debug(f"First 4 bytes don't seem to be a valid point count: LE={num_points_le}, BE={num_points_be}")
                        has_header = False
                        
                except Exception as e:
                    path.log_debug(f"Failed to interpret first 4 bytes as point count: {str(e)}")
                    has_header = False
            
            # If we couldn't detect a header or the count seems invalid, estimate from file size
            if not has_header:
                # Estimate based on typical point size (7 or 8 floats per point)
                estimated_points_7f = len(file_data) // 28  # 7 floats * 4 bytes
                estimated_points_8f = len(file_data) // 32  # 8 floats * 4 bytes
                
                path.log_debug(f"No clear header. Estimated points: {estimated_points_7f} (7 floats) or {estimated_points_8f} (8 floats)")
                
                # Start trying to parse points from the beginning
                offset = 0
                num_points = max(estimated_points_7f, estimated_points_8f)
            
            # Try to parse points
            point_size_options = [28, 32]  # 7 or 8 floats per point
            
            for point_size in point_size_options:
                # Reset points list
                path.points = []
                current_offset = offset
                success_count = 0
                failure_count = 0
                
                path.log_debug(f"Trying to parse with point size {point_size} bytes")
                
                for i in range(num_points if num_points else 1000):  # Limit to prevent infinite loop
                    if current_offset + point_size > len(file_data):
                        path.log_debug(f"Reached end of file at point {i}")
                        break
                        
                    try:
                        if point_size == 28:
                            # 7 floats (x, y, z, dx, dy, dz, turn_brake)
                            values = struct.unpack('<7f', file_data[current_offset:current_offset+28])
                            point = AITrackPoint(
                                x=values[0], y=values[1], z=values[2],
                                dx=values[3], dy=values[4], dz=values[5],
                                turn_brake=values[6]
                            )
                        else:  # point_size == 32
                            # 8 floats (with placeholder)
                            values = struct.unpack('<8f', file_data[current_offset:current_offset+32])
                            point = AITrackPoint(
                                x=values[0], y=values[1], z=values[2],
                                dx=values[3], dy=values[4], dz=values[5],
                                turn_brake=values[6],
                                placeholder=values[7]
                            )
                            
                        # Validate the point - check if values are reasonable
                        is_valid = all(abs(v) < 10000 for v in values)
                        
                        if is_valid:
                            path.points.append(point)
                            success_count += 1
                            current_offset += point_size
                        else:
                            path.log_debug(f"Invalid point values at offset {current_offset}: {values}")
                            failure_count += 1
                            current_offset += 4  # Skip one float and try again
                            
                    except Exception as e:
                        path.log_debug(f"Failed to parse point at offset {current_offset}: {str(e)}")
                        failure_count += 1
                        current_offset += 4  # Skip one float and try again
                        
                    # Stop if too many failures
                    if failure_count > 20 and success_count == 0:
                        path.log_debug(f"Too many failures with point size {point_size}, trying next option")
                        break
                
                # If we found a good number of points, stop trying different sizes
                if success_count > 5:
                    path.log_debug(f"Successfully parsed {success_count} points with size {point_size}")
                    break
            
            if not path.points:
                path.log_debug("Could not parse any points. Attempting raw bytes analysis.")
                
                # Last resort: try to find float sequences in the raw data
                current_offset = 0
                while current_offset + 28 <= len(file_data):
                    try:
                        values = struct.unpack('<7f', file_data[current_offset:current_offset+28])
                        
                        # Check if values look reasonable for a point
                        is_valid = all(abs(v) < 10000 for v in values)
                        
                        if is_valid:
                            point = AITrackPoint(
                                x=values[0], y=values[1], z=values[2],
                                dx=values[3], dy=values[4], dz=values[5],
                                turn_brake=values[6]
                            )
                            path.points.append(point)
                            current_offset += 28
                        else:
                            current_offset += 4
                    except:
                        current_offset += 4
            
            path.log_debug(f"Final result: {len(path.points)} points parsed")
                
        except Exception as e:
            print(f"Error reading binary file: {str(e)}")
            traceback.print_exc()
            
        return path
    
    def to_csv(self, filename, include_header=True, separator=', '):
        """Save track to CSV file"""
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                # Write number of points as header if requested
                if include_header:
                    f.write(f"{len(self.points)}\n")
                
                # Write each point
                for point in self.points:
                    f.write(point.to_csv_line(separator) + "\n")
                    
            print(f"Saved {len(self.points)} points to {filename}")
            return True
        except Exception as e:
            print(f"Error saving CSV file: {str(e)}")
            traceback.print_exc()
            return False
    
    def to_binary(self, filename, include_placeholder=True):
        """Save track to binary REC file"""
        try:
            with open(filename, 'wb') as f:
                # Write number of points header
                f.write(struct.pack('<i', len(self.points)))
                
                # Write each point
                for point in self.points:
                    if include_placeholder:
                        # Write 8 floats per point (including placeholder)
                        f.write(struct.pack('<8f', 
                            point.x, point.y, point.z,
                            point.dx, point.dy, point.dz,
                            point.turn_brake, point.placeholder
                        ))
                    else:
                        # Write 7 floats per point
                        f.write(struct.pack('<7f', 
                            point.x, point.y, point.z,
                            point.dx, point.dy, point.dz,
                            point.turn_brake
                        ))
                    
            print(f"Saved {len(self.points)} points to {filename}")
            return True
        except Exception as e:
            print(f"Error saving binary file: {str(e)}")
            traceback.print_exc()
            return False
    
    def to_obj(self, filename):
        """Export track to OBJ file format"""
        try:
            with open(filename, 'w') as f:
                # Write OBJ header
                f.write("# AI Track Path OBJ File\n")
                f.write("# Generated by AI Track Converter Tool v{}\n".format(VERSION))
                f.write(f"# Points: {len(self.points)}\n\n")
                
                # Write vertex data
                for i, point in enumerate(self.points):
                    f.write(f"v {point.x} {point.y} {point.z}\n")
                
                # Write custom metadata
                f.write("\n# AI Track Metadata (do not edit these lines)\n")
                for i, point in enumerate(self.points):
                    # Store direction and turn/brake data in comments for later import
                    max_speed, turn_strength = point.calculate_speed_and_turn()
                    f.write(f"# AIPOINT {i+1} {point.dx} {point.dy} {point.dz} {max_speed} {turn_strength}\n")
                
                # Create a line connecting all points
                f.write("\n# Line segments\n")
                for i in range(1, len(self.points)):
                    f.write(f"l {i} {i+1}\n")
                
                # Connect last point to first to complete the loop
                if len(self.points) > 2:
                    f.write(f"l {len(self.points)} 1\n")
                    
            print(f"Exported track to {filename}")
            return True
        except Exception as e:
            print(f"Error exporting OBJ file: {str(e)}")
            traceback.print_exc()
            return False
    
    def to_dxf(self, filename):
        """Export track to DXF file format (simplified)"""
        try:
            with open(filename, 'w') as f:
                # DXF header
                f.write("0\nSECTION\n2\nHEADER\n0\nENDSEC\n")
                f.write("0\nSECTION\n2\nENTITIES\n")
                
                # Write polyline
                f.write("0\nPOLYLINE\n")
                f.write("8\nAI_TRACK\n")  # Layer name
                f.write("66\n1\n")  # Vertices follow
                f.write("70\n1\n")  # Closed polyline
                
                # Write vertices
                for point in self.points:
                    f.write("0\nVERTEX\n")
                    f.write("8\nAI_TRACK\n")
                    f.write(f"10\n{point.x}\n")
                    f.write(f"20\n{point.z}\n")  # Note: DXF typically uses Y for the 2nd coordinate
                    f.write(f"30\n{point.y}\n")  # We're swapping Y and Z to match racing game conventions
                    
                    # Store metadata in extended data
                    max_speed, turn_strength = point.calculate_speed_and_turn()
                    f.write("1\n")  # XDATA marker
                    f.write(f"AIPOINT {point.dx} {point.dy} {point.dz} {max_speed} {turn_strength}\n")
                    
                # End polyline
                f.write("0\nSEQEND\n")
                
                # End file
                f.write("0\nENDSEC\n0\nEOF\n")
                
            print(f"Exported track to {filename}")
            return True
        except Exception as e:
            print(f"Error exporting DXF file: {str(e)}")
            traceback.print_exc()
            return False
    
    @classmethod
    def from_obj(cls, filename):
        """Import track from OBJ file"""
        path = cls()
        vertices = []
        metadata = {}
        
        try:
            with open(filename, 'r') as f:
                for line in f:
                    if line.startswith('v '):
                        # Parse vertex
                        parts = line.strip().split()
                        if len(parts) >= 4:
                            x, y, z = float(parts[1]), float(parts[2]), float(parts[3])
                            vertices.append((x, y, z))
                            
                    elif line.startswith('# AIPOINT '):
                        # Parse metadata
                        parts = line.strip().split()
                        if len(parts) >= 7:
                            index = int(parts[2]) - 1
                            dx, dy, dz = float(parts[3]), float(parts[4]), float(parts[5])
                            max_speed, turn_strength = float(parts[6]), float(parts[7])
                            metadata[index] = (dx, dy, dz, max_speed, turn_strength)
            
            # Construct points from vertices and metadata
            for i, (x, y, z) in enumerate(vertices):
                point = AITrackPoint(x=x, y=y, z=z)
                
                # Apply metadata if available
                if i in metadata:
                    dx, dy, dz, max_speed, turn_strength = metadata[i]
                    point.dx, point.dy, point.dz = dx, dy, dz
                    point.set_speed_and_turn(max_speed, turn_strength)
                
                path.points.append(point)
        except Exception as e:
            print(f"Error reading OBJ file: {str(e)}")
            traceback.print_exc()
                
        return path
    
    @classmethod
    def from_dxf(cls, filename):
        """Import track from DXF file"""
        path = cls()
        vertices = []
        metadata = []
        
        try:
            with open(filename, 'r') as f:
                lines = f.readlines()
                
            i = 0
            while i < len(lines):
                line = lines[i].strip()
                
                if line == "0" and i+1 < len(lines) and lines[i+1].strip() == "VERTEX":
                    # Found a vertex
                    x, y, z = 0, 0, 0
                    dx, dy, dz = 0, 0, 0
                    max_speed, turn_strength = 1.0, 0.0
                    
                    # Parse vertex coordinates
                    j = i + 2
                    while j < len(lines):
                        if lines[j].strip() == "0":
                            break
                        
                        code = lines[j].strip()
                        if j+1 < len(lines):
                            value = lines[j+1].strip()
                            
                            if code == "10":
                                x = float(value)
                            elif code == "20":
                                z = float(value)  # Swapped with Y in DXF
                            elif code == "30":
                                y = float(value)  # Swapped with Z in DXF
                            elif code == "1" and "AIPOINT" in value:
                                # Parse metadata
                                parts = value.split()
                                if len(parts) >= 5:
                                    dx, dy, dz = float(parts[1]), float(parts[2]), float(parts[3])
                                    max_speed, turn_strength = float(parts[4]), float(parts[5])
                                    
                        j += 2
                    
                    # Create point
                    point = AITrackPoint(x=x, y=y, z=z, dx=dx, dy=dy, dz=dz)
                    point.set_speed_and_turn(max_speed, turn_strength)
                    path.points.append(point)
                    
                    i = j
                else:
                    i += 1
        except Exception as e:
            print(f"Error reading DXF file: {str(e)}")
            traceback.print_exc()
                
        return path
    
    @classmethod
    def open_file(cls, filename, debug=False):
        """Detect file type and open accordingly"""
        file_type = cls.detect_file_type(filename)
        
        if debug:
            print(f"Detected file type: {file_type}")
        
        if file_type == 'csv':
            return cls.from_csv(filename, debug)
        elif file_type == 'rec':
            return cls.from_binary(filename, debug)
        elif file_type == 'obj':
            return cls.from_obj(filename)
        elif file_type == 'dxf':
            return cls.from_dxf(filename)
        else:
            raise ValueError(f"Could not determine file type for {filename}")
    
    def analyze(self):
        """Analyze the track and report statistics"""
        if not self.points:
            return "No points in track"
            
        result = []
        result.append(f"Track Analysis:")
        result.append(f"  Number of points: {len(self.points)}")
        
        # Calculate track length
        length = 0
        for i in range(len(self.points)):
            p1 = self.points[i]
            p2 = self.points[(i+1) % len(self.points)]
            dx = p2.x - p1.x
            dy = p2.y - p1.y
            dz = p2.z - p1.z
            segment_length = math.sqrt(dx*dx + dy*dy + dz*dz)
            length += segment_length
            
        result.append(f"  Total track length: {length:.2f} units")
        
        # Speed statistics
        speeds = [p.calculate_speed_and_turn()[0] for p in self.points]
        avg_speed = sum(speeds) / len(speeds)
        min_speed = min(speeds)
        max_speed = max(speeds)
        
        result.append(f"  Average speed setting: {avg_speed:.2f}")
        result.append(f"  Minimum speed setting: {min_speed:.2f}")
        result.append(f"  Maximum speed setting: {max_speed:.2f}")
        
        # Turn statistics
        turns = [p.calculate_speed_and_turn()[1] for p in self.points]
        
        result.append(f"  Turn strength range: {min(turns):.2f} to {max(turns):.2f}")
        
        return "\n".join(result)
    
    def optimize(self):
        """Apply automatic optimizations to the track"""
        if len(self.points) < 3:
            return "Not enough points to optimize"
            
        # Calculate curvature at each point
        curvatures = []
        for i in range(len(self.points)):
            prev_idx = (i - 1) % len(self.points)
            next_idx = (i + 1) % len(self.points)
            
            p_prev = self.points[prev_idx]
            p_curr = self.points[i]
            p_next = self.points[next_idx]
            
            # Calculate vectors
            v1 = np.array([p_curr.x - p_prev.x, p_curr.y - p_prev.y, p_curr.z - p_prev.z])
            v2 = np.array([p_next.x - p_curr.x, p_next.y - p_curr.y, p_next.z - p_curr.z])
            
            # Normalize
            v1_norm = np.linalg.norm(v1)
            v2_norm = np.linalg.norm(v2)
            
            if v1_norm > 0 and v2_norm > 0:
                v1 = v1 / v1_norm
                v2 = v2 / v2_norm
                
                # Calculate angle
                dot_product = np.clip(np.dot(v1, v2), -1.0, 1.0)
                angle = math.acos(dot_product)
                
                # Calculate curvature (higher means sharper turn)
                curvature = angle / (v1_norm + v2_norm) * 2
            else:
                curvature = 0
                
            curvatures.append(curvature)
        
        # Apply speed and turn settings based on curvature
        for i, curvature in enumerate(curvatures):
            # Set turn strength based on curvature
            turn_strength = min(1.0, max(-2.0, curvature * 10 - 0.5))
            
            # Set speed based on curvature
            if curvature > 0.1:  # Sharp turn
                max_speed = max(0.3, 1.0 - curvature * 5)
            else:  # Straight or gentle turn
                max_speed = 1.0
                
            # Apply settings
            self.points[i].set_speed_and_turn(max_speed, turn_strength)
            
        return "Optimized track based on curvature"
        
    def adjust_braking_points(self, num_points=2):
        """Adjusts braking points before turns to be more realistic"""
        if len(self.points) < 3:
            return "Not enough points to adjust braking"
            
        # Find all turns (points with speed < 1.0)
        turns = []
        for i, point in enumerate(self.points):
            max_speed, _ = point.calculate_speed_and_turn()
            if max_speed < 0.95:  # This is a turn with braking
                turns.append(i)
                
        # For each turn, adjust the braking points leading up to it
        for turn_idx in turns:
            # Get the turn's speed
            turn_speed, _ = self.points[turn_idx].calculate_speed_and_turn()
            
            # Calculate braking points before the turn
            for j in range(1, num_points + 1):
                brake_idx = (turn_idx - j) % len(self.points)
                
                # Calculate a gradual braking profile
                brake_fraction = j / (num_points + 1)
                target_speed = 1.0 - (1.0 - turn_speed) * (1 - brake_fraction)
                
                # Get current settings
                _, turn_strength = self.points[brake_idx].calculate_speed_and_turn()
                
                # Apply brake setting (but only if it would slow down the point)
                current_speed, _ = self.points[brake_idx].calculate_speed_and_turn()
                if target_speed < current_speed:
                    self.points[brake_idx].set_speed_and_turn(target_speed, turn_strength)
                    
        return f"Adjusted braking points before {len(turns)} turns"


class AITrackEditorGUI:
    def __init__(self, root, initial_file=None):
        self.root = root
        self.root.title("AI Track Editor Tool v{}".format(VERSION))
        self.root.geometry("1200x800")
        
        self.track = None
        self.selected_point = None
        self.filename = None
        self.debug_mode = tk.BooleanVar(value=False)
        
        self.setup_ui()
        
        # Load initial file if provided
        if initial_file:
            self.load_track_file(initial_file)
        
    def setup_ui(self):
        # Create main frame
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # Left sidebar for controls
        control_frame = ttk.LabelFrame(main_frame, text="Controls")
        control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
        
        # File operations
        file_frame = ttk.LabelFrame(control_frame, text="File Operations")
        file_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Button(file_frame, text="Open Track", command=self.open_track).pack(fill=tk.X, padx=5, pady=2)
        ttk.Button(file_frame, text="Save Track", command=self.save_track).pack(fill=tk.X, padx=5, pady=2)
        
        export_frame = ttk.Frame(file_frame)
        export_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Button(export_frame, text="Export CSV", command=lambda: self.export_track('csv')).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        ttk.Button(export_frame, text="Export REC", command=lambda: self.export_track('rec')).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        
        export_frame2 = ttk.Frame(file_frame)
        export_frame2.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Button(export_frame2, text="Export OBJ", command=lambda: self.export_track('obj')).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        ttk.Button(export_frame2, text="Export DXF", command=lambda: self.export_track('dxf')).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        
        # Debug mode toggle
        debug_frame = ttk.Frame(file_frame)
        debug_frame.pack(fill=tk.X, padx=5, pady=2)
        ttk.Checkbutton(debug_frame, text="Debug Mode", variable=self.debug_mode).pack(side=tk.LEFT, padx=5)
        
        # Analysis and optimization
        analysis_frame = ttk.LabelFrame(control_frame, text="Analysis & Optimization")
        analysis_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Button(analysis_frame, text="Analyze Track", command=self.analyze_track).pack(fill=tk.X, padx=5, pady=2)
        ttk.Button(analysis_frame, text="Auto-Optimize", command=self.optimize_track).pack(fill=tk.X, padx=5, pady=2)
        
        # Braking adjustment
        braking_frame = ttk.LabelFrame(control_frame, text="Braking Adjustment")
        braking_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(braking_frame, text="Braking Points:").pack(padx=5, pady=2)
        self.brake_points_var = tk.StringVar(value="2")
        ttk.Spinbox(braking_frame, from_=1, to=5, textvariable=self.brake_points_var).pack(fill=tk.X, padx=5, pady=2)
        ttk.Button(braking_frame, text="Apply Braking", command=self.adjust_braking).pack(fill=tk.X, padx=5, pady=2)
        
        # Point editor
        point_frame = ttk.LabelFrame(control_frame, text="Point Editor")
        point_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # Point selection
        point_select_frame = ttk.Frame(point_frame)
        point_select_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(point_select_frame, text="Selected Point:").pack(side=tk.LEFT, padx=5)
        self.point_var = tk.StringVar()
        self.point_dropdown = ttk.Combobox(point_select_frame, textvariable=self.point_var, state="readonly")
        self.point_dropdown.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        self.point_dropdown.bind("<<ComboboxSelected>>", self.on_point_selected)
        
        # Navigation buttons
        nav_frame = ttk.Frame(point_frame)
        nav_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Button(nav_frame, text="◀ Prev", command=self.prev_point).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        ttk.Button(nav_frame, text="Next ▶", command=self.next_point).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
        
        # Speed editor
        speed_frame = ttk.Frame(point_frame)
        speed_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(speed_frame, text="Speed:").pack(side=tk.LEFT, padx=5)
        self.speed_var = tk.DoubleVar(value=1.0)
        self.speed_value = ttk.Label(speed_frame, text="1.00")
        self.speed_value.pack(side=tk.RIGHT, padx=5)
        
        self.speed_scale = ttk.Scale(point_frame, from_=0.2, to=1.0, orient=tk.HORIZONTAL, 
                              variable=self.speed_var, command=self.on_speed_changed)
        self.speed_scale.pack(fill=tk.X, padx=5, pady=2)
        
        # Turn editor
        turn_frame = ttk.Frame(point_frame)
        turn_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(turn_frame, text="Turn Strength:").pack(side=tk.LEFT, padx=5)
        self.turn_var = tk.DoubleVar(value=0.0)
        self.turn_value = ttk.Label(turn_frame, text="0.00")
        self.turn_value.pack(side=tk.RIGHT, padx=5)
        
        self.turn_scale = ttk.Scale(point_frame, from_=-2.0, to=1.0, orient=tk.HORIZONTAL, 
                            variable=self.turn_var, command=self.on_turn_changed)
        self.turn_scale.pack(fill=tk.X, padx=5, pady=2)
        
        # Raw value editor
        raw_frame = ttk.Frame(point_frame)
        raw_frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(raw_frame, text="Raw Value:").pack(side=tk.LEFT, padx=5)
        self.raw_var = tk.StringVar(value="0.0")
        self.raw_entry = ttk.Entry(raw_frame, textvariable=self.raw_var, width=10)
        self.raw_entry.pack(side=tk.LEFT, padx=5)
        ttk.Button(raw_frame, text="Set", command=self.set_raw_value).pack(side=tk.LEFT, padx=5)
        
        # Coordinate info
        coords_frame = ttk.LabelFrame(control_frame, text="Coordinates")
        coords_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # X coordinate
        x_frame = ttk.Frame(coords_frame)
        x_frame.pack(fill=tk.X, padx=5, pady=2)
        ttk.Label(x_frame, text="X:").pack(side=tk.LEFT, padx=5)
        self.x_var = tk.StringVar(value="0.0")
        self.x_entry = ttk.Entry(x_frame, textvariable=self.x_var, width=10)
        self.x_entry.pack(side=tk.LEFT, padx=5)
        
        # Y coordinate
        y_frame = ttk.Frame(coords_frame)
        y_frame.pack(fill=tk.X, padx=5, pady=2)
        ttk.Label(y_frame, text="Y:").pack(side=tk.LEFT, padx=5)
        self.y_var = tk.StringVar(value="0.0")
        self.y_entry = ttk.Entry(y_frame, textvariable=self.y_var, width=10)
        self.y_entry.pack(side=tk.LEFT, padx=5)
        
        # Z coordinate
        z_frame = ttk.Frame(coords_frame)
        z_frame.pack(fill=tk.X, padx=5, pady=2)
        ttk.Label(z_frame, text="Z:").pack(side=tk.LEFT, padx=5)
        self.z_var = tk.StringVar(value="0.0")
        self.z_entry = ttk.Entry(z_frame, textvariable=self.z_var, width=10)
        self.z_entry.pack(side=tk.LEFT, padx=5)
        
        # Update coordinates button
        ttk.Button(coords_frame, text="Update Coordinates", command=self.update_coordinates).pack(fill=tk.X, padx=5, pady=2)
        
        # Status indicator
        status_frame = ttk.Frame(control_frame)
        status_frame.pack(fill=tk.X, padx=5, pady=5)
        self.status_var = tk.StringVar(value="No track loaded")
        ttk.Label(status_frame, textvariable=self.status_var).pack(anchor=tk.W)
        
        # Right side for visualization
        viz_frame = ttk.LabelFrame(main_frame, text="Track Visualization")
        viz_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        # Create matplotlib figure
        self.fig = Figure(figsize=(8, 6), dpi=100)
        self.ax1 = self.fig.add_subplot(211)  # Top plot (top-down view)
        self.ax2 = self.fig.add_subplot(212)  # Bottom plot (speed/turn profile)
        
        # Create canvas
        self.canvas = FigureCanvasTkAgg(self.fig, master=viz_frame)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # Add toolbar
        from matplotlib.backends.backend_tkagg import NavigationToolbar2Tk
        toolbar_frame = ttk.Frame(viz_frame)
        toolbar_frame.pack(fill=tk.X)
        toolbar = NavigationToolbar2Tk(self.canvas, toolbar_frame)
        toolbar.update()
        
        # Configure axes
        self.ax1.set_title("Track Layout")
        self.ax1.set_aspect('equal')
        self.ax1.grid(True)
        
        self.ax2.set_title("Speed & Turn Profile")
        self.ax2.set_xlabel("Point Index")
        self.ax2.set_ylabel("Value")
        self.ax2.grid(True)
        
        # Add a click handler to select points on the plot
        self.canvas.mpl_connect('button_press_event', self.on_plot_click)
        
        # Update layout
        self.fig.tight_layout()
        
    def on_plot_click(self, event):
        """Handle clicks on the plot to select points"""
        if not self.track or event.inaxes != self.ax1:
            return
            
        if not self.track.points:
            return
            
        x_coords = [p.x for p in self.track.points]
        z_coords = [p.z for p in self.track.points]
        
        # Find the closest point
        min_dist = float('inf')
        closest_idx = 0
        
        for i, (x, z) in enumerate(zip(x_coords, z_coords)):
            dist = (x - event.xdata) ** 2 + (z - event.ydata) ** 2
            if dist < min_dist:
                min_dist = dist
                closest_idx = i
                
        # Select the point
        self.selected_point = closest_idx
        self.point_dropdown.current(closest_idx)
        self.update_point_editor(closest_idx)
        self.update_visualization(highlight_point=closest_idx)
    
    def load_track_file(self, filepath):
        """Load a track from file"""
        try:
            debug_mode = self.debug_mode.get()
            # Use the improved file detection and loading method
            self.track = AITrackPath.open_file(filepath, debug=debug_mode)
                
            if not self.track or not self.track.points:
                messagebox.showerror("Error", "Failed to load track or track is empty")
                return False
                
            self.filename = filepath
            self.status_var.set(f"Loaded: {os.path.basename(filepath)} ({len(self.track.points)} points)")
            
            # Update UI
            self.update_point_dropdown()
            self.update_visualization()
            return True
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to load track: {str(e)}")
            traceback.print_exc()
            return False
    
    def open_track(self):
        """Open track file dialog"""
        filetypes = [
            ("All Supported Files", "*.csv;*.rec;*.bin;*.*"),
            ("CSV Files", "*.csv"),
            ("REC Files", "*.rec;*.bin"),
            ("OBJ Files", "*.obj"),
            ("DXF Files", "*.dxf"),
            ("All Files", "*.*")
        ]
        
        filepath = filedialog.askopenfilename(
            title="Open Track File",
            filetypes=filetypes
        )
        
        if not filepath:
            return
            
        self.load_track_file(filepath)
    
    def save_track(self):
        """Save track to file"""
        if not self.track:
            messagebox.showinfo("Info", "No track loaded")
            return
            
        if not self.filename:
            self.export_track('csv')
            return
            
        # Save to the same format
        file_type = AITrackPath.detect_file_type(self.filename)
        
        try:
            success = False
            if file_type == 'csv':
                success = self.track.to_csv(self.filename)
            elif file_type == 'rec':
                success = self.track.to_binary(self.filename)
            elif file_type == 'obj':
                success = self.track.to_obj(self.filename)
            elif file_type == 'dxf':
                success = self.track.to_dxf(self.filename)
            else:
                messagebox.showerror("Error", f"Unsupported file type: {file_type}")
                return
                
            if success:
                messagebox.showinfo("Success", f"Track saved to {self.filename}")
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to save track: {str(e)}")
            traceback.print_exc()
    
    def export_track(self, format_type):
        """Export track to specific format"""
        if not self.track:
            messagebox.showinfo("Info", "No track loaded")
            return
            
        # Set up file dialog based on format
        if format_type == 'csv':
            filetypes = [("CSV Files", "*.csv")]
            default_ext = ".csv"
        elif format_type == 'rec':
            filetypes = [("REC Files", "*.rec"), ("Binary Files", "*")]
            default_ext = ".rec"
        elif format_type == 'obj':
            filetypes = [("OBJ Files", "*.obj")]
            default_ext = ".obj"
        elif format_type == 'dxf':
            filetypes = [("DXF Files", "*.dxf")]
            default_ext = ".dxf"
        else:
            messagebox.showerror("Error", f"Unsupported export format: {format_type}")
            return
            
        filepath = filedialog.asksaveasfilename(
            title=f"Export as {format_type.upper()}",
            filetypes=filetypes,
            defaultextension=default_ext
        )
        
        if not filepath:
            return
            
        try:
            success = False
            if format_type == 'csv':
                success = self.track.to_csv(filepath)
            elif format_type == 'rec':
                success = self.track.to_binary(filepath)
            elif format_type == 'obj':
                success = self.track.to_obj(filepath)
            elif format_type == 'dxf':
                success = self.track.to_dxf(filepath)
                
            if success:
                messagebox.showinfo("Success", f"Track exported to {filepath}")
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to export track: {str(e)}")
            traceback.print_exc()
    
    def analyze_track(self):
        """Analyze track and show statistics"""
        if not self.track:
            messagebox.showinfo("Info", "No track loaded")
            return
            
        analysis = self.track.analyze()
        messagebox.showinfo("Track Analysis", analysis)
    
    def optimize_track(self):
        """Auto-optimize track"""
        if not self.track:
            messagebox.showinfo("Info", "No track loaded")
            return
            
        result = self.track.optimize()
        messagebox.showinfo("Optimization Result", result)
        
        # Update UI
        self.update_visualization()
        if self.selected_point is not None:
            self.update_point_editor(self.selected_point)
    
    def adjust_braking(self):
        """Adjust braking points"""
        if not self.track:
            messagebox.showinfo("Info", "No track loaded")
            return
            
        try:
            brake_points = int(self.brake_points_var.get())
            result = self.track.adjust_braking_points(brake_points)
            messagebox.showinfo("Braking Adjustment", result)
            
            # Update UI
            self.update_visualization()
            if self.selected_point is not None:
                self.update_point_editor(self.selected_point)
                
        except Exception as e:
            messagebox.showerror("Error", f"Failed to adjust braking: {str(e)}")
            traceback.print_exc()
    
    def update_point_dropdown(self):
        """Update the point selection dropdown"""
        if not self.track or not self.track.points:
            return
            
        values = [f"Point {i+1}" for i in range(len(self.track.points))]
        self.point_dropdown['values'] = values
        self.point_dropdown.current(0)
        self.selected_point = 0
        self.update_point_editor(0)
    
    def on_point_selected(self, event):
        """Handle point selection from dropdown"""
        if not self.track:
            return
            
        selected = self.point_dropdown.current()
        if selected >= 0 and selected < len(self.track.points):
            self.selected_point = selected
            self.update_point_editor(selected)
            self.update_visualization(highlight_point=selected)
    
    def prev_point(self):
        """Select the previous point"""
        if not self.track or self.selected_point is None:
            return
            
        new_idx = (self.selected_point - 1) % len(self.track.points)
        self.selected_point = new_idx
        self.point_dropdown.current(new_idx)
        self.update_point_editor(new_idx)
        self.update_visualization(highlight_point=new_idx)
    
    def next_point(self):
        """Select the next point"""
        if not self.track or self.selected_point is None:
            return
            
        new_idx = (self.selected_point + 1) % len(self.track.points)
        self.selected_point = new_idx
        self.point_dropdown.current(new_idx)
        self.update_point_editor(new_idx)
        self.update_visualization(highlight_point=new_idx)
    
    def update_point_editor(self, point_index):
        """Update point editor controls for the selected point"""
        if not self.track or point_index is None:
            return
            
        point = self.track.points[point_index]
        max_speed, turn_strength = point.calculate_speed_and_turn()
        
        # Update speed and turn sliders without triggering events
        self.speed_var.set(max_speed)
        self.turn_var.set(turn_strength)
        
        # Update labels
        self.speed_value.config(text=f"{max_speed:.2f}")
        self.turn_value.config(text=f"{turn_strength:.2f}")
        
        # Update raw value
        self.raw_var.set(f"{point.turn_brake:.2f}")
        
        # Update coordinates
        self.x_var.set(f"{point.x:.2f}")
        self.y_var.set(f"{point.y:.2f}")
        self.z_var.set(f"{point.z:.2f}")
    
    def on_speed_changed(self, event):
        """Handle speed slider change"""
        if not self.track or self.selected_point is None:
            return
            
        try:
            max_speed = self.speed_var.get()
            self.speed_value.config(text=f"{max_speed:.2f}")
            
            _, turn_strength = self.track.points[self.selected_point].calculate_speed_and_turn()
            self.track.points[self.selected_point].set_speed_and_turn(max_speed, turn_strength)
            
            # Update raw value
            self.raw_var.set(f"{self.track.points[self.selected_point].turn_brake:.2f}")
            
            self.update_visualization(highlight_point=self.selected_point)
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to update speed: {str(e)}")
            traceback.print_exc()
    
    def on_turn_changed(self, event):
        """Handle turn slider change"""
        if not self.track or self.selected_point is None:
            return
            
        try:
            turn_strength = self.turn_var.get()
            self.turn_value.config(text=f"{turn_strength:.2f}")
            
            max_speed, _ = self.track.points[self.selected_point].calculate_speed_and_turn()
            self.track.points[self.selected_point].set_speed_and_turn(max_speed, turn_strength)
            
            # Update raw value
            self.raw_var.set(f"{self.track.points[self.selected_point].turn_brake:.2f}")
            
            self.update_visualization(highlight_point=self.selected_point)
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to update turn strength: {str(e)}")
            traceback.print_exc()
    
    def set_raw_value(self):
        """Set the raw turn_brake value"""
        if not self.track or self.selected_point is None:
            return
            
        try:
            raw_value = float(self.raw_var.get())
            self.track.points[self.selected_point].turn_brake = raw_value
            
            # Update sliders
            max_speed, turn_strength = self.track.points[self.selected_point].calculate_speed_and_turn()
            self.speed_var.set(max_speed)
            self.turn_var.set(turn_strength)
            self.speed_value.config(text=f"{max_speed:.2f}")
            self.turn_value.config(text=f"{turn_strength:.2f}")
            
            self.update_visualization(highlight_point=self.selected_point)
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to set raw value: {str(e)}")
            traceback.print_exc()
    
    def update_coordinates(self):
        """Update the coordinates of the selected point"""
        if not self.track or self.selected_point is None:
            return
            
        try:
            x = float(self.x_var.get())
            y = float(self.y_var.get())
            z = float(self.z_var.get())
            
            self.track.points[self.selected_point].x = x
            self.track.points[self.selected_point].y = y
            self.track.points[self.selected_point].z = z
            
            self.update_visualization(highlight_point=self.selected_point)
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to update coordinates: {str(e)}")
            traceback.print_exc()
    
    def update_visualization(self, highlight_point=None):
        """Update track visualization"""
        if not self.track or not self.track.points:
            return
            
        # Clear plots
        self.ax1.clear()
        self.ax2.clear()
        
        # Get track data
        x_coords = [p.x for p in self.track.points]
        z_coords = [p.z for p in self.track.points]  # Using Z as Y for top-down view
        
        speeds = [p.calculate_speed_and_turn()[0] for p in self.track.points]
        turns = [p.calculate_speed_and_turn()[1] for p in self.track.points]
        indices = list(range(len(self.track.points)))
        
        # Plot top-down view with color based on speed
        scatter = self.ax1.scatter(x_coords, z_coords, c=speeds, cmap='coolwarm', 
                           vmin=0.2, vmax=1.0, s=50, zorder=2)
        
        # Connect points with lines
        self.ax1.plot(x_coords + [x_coords[0]], z_coords + [z_coords[0]], 'k-', alpha=0.5, zorder=1)
        
        # Add point numbers
        for i, (x, z) in enumerate(zip(x_coords, z_coords)):
            self.ax1.annotate(str(i+1), (x, z), fontsize=8, ha='center', va='center')
        
        # Add colorbar
        self.fig.colorbar(scatter, ax=self.ax1, label='Speed')
        
        # Highlight selected point
        if highlight_point is not None and 0 <= highlight_point < len(self.track.points):
            self.ax1.plot(x_coords[highlight_point], z_coords[highlight_point], 'o', 
                        color='lime', markersize=12, markeredgecolor='black', zorder=3)
        
        # Plot speed and turn profiles
        self.ax2.plot(indices, speeds, 'b-', label='Speed')
        self.ax2.plot(indices, [t/5 + 0.5 for t in turns], 'r-', label='Turn Strength (scaled)')
        
        # Highlight selected point in profile
        if highlight_point is not None and 0 <= highlight_point < len(self.track.points):
            self.ax2.axvline(x=highlight_point, color='green', linestyle='--', alpha=0.7)
        
        # Set labels and legend
        self.ax1.set_title("Track Layout")
        self.ax1.set_xlabel("X Coordinate")
        self.ax1.set_ylabel("Z Coordinate")
        self.ax1.grid(True)
        self.ax1.set_aspect('equal')
        
        self.ax2.set_title("Speed & Turn Profile")
        self.ax2.set_xlabel("Point Index")
        self.ax2.set_ylabel("Value")
        self.ax2.set_ylim([-0.5, 1.5])
        self.ax2.legend()
        self.ax2.grid(True)
        
        # Update layout
        self.fig.tight_layout()
        self.canvas.draw()


def run_gui(initial_file=None):
    """Run the GUI application"""
    root = tk.Tk()
    app = AITrackEditorGUI(root, initial_file)
    root.mainloop()


def run_cli(args):
    """Run the command-line application"""
    if args.command == 'help':
        print_help()
        return
    
    if not args.input and args.command != 'help':
        print("Error: Input file is required")
        return
    
    # Load track from input file
    try:
        if args.command != 'help':
            track = AITrackPath.open_file(args.input, debug=args.debug)
            
            if not track or not track.points:
                print("Error: Failed to load track or track has no points")
                return
    except Exception as e:
        print(f"Error loading track: {str(e)}")
        if args.debug:
            traceback.print_exc()
        return
    
    # Execute command
    if args.command == 'analyze':
        print(track.analyze())
        
    elif args.command == 'optimize':
        print(track.optimize())
        if args.output:
            save_track(track, args.output, args.format)
            
    elif args.command == 'adjust':
        print(track.adjust_braking_points(args.brake_points))
        if args.output:
            save_track(track, args.output, args.format)
            
    elif args.command == 'convert':
        if not args.output:
            print("Error: Output file is required for convert command")
            return
            
        save_track(track, args.output, args.format)


def save_track(track, output_file, format_override=None):
    """Save track to the specified output file"""
    # Determine output format
    if format_override:
        output_format = format_override
    else:
        # Try to detect from extension
        _, ext = os.path.splitext(output_file)
        if ext:
            ext = ext.lower()
            if ext == '.csv':
                output_format = 'csv'
            elif ext in ['.rec', '.bin']:
                output_format = 'rec'
            elif ext == '.obj':
                output_format = 'obj'
            elif ext == '.dxf':
                output_format = 'dxf'
            else:
                print(f"Warning: Unrecognized extension '{ext}', defaulting to CSV format")
                output_format = 'csv'
        else:
            # No extension - default to type based on filename
            if output_file.lower() == 'rec':
                output_format = 'rec'
            else:
                output_format = 'csv'
    
    # Save in the appropriate format
    success = False
    if output_format == 'csv':
        success = track.to_csv(output_file)
    elif output_format == 'rec':
        success = track.to_binary(output_file)
    elif output_format == 'obj':
        success = track.to_obj(output_file)
    elif output_format == 'dxf':
        success = track.to_dxf(output_file)
        
    if not success:
        print(f"Failed to save track to {output_file}")


def print_help():
    """Print detailed help information"""
    help_text = f"""
AI Track Tool v{VERSION} - Help
========================

Commands:
  gui       - Launch graphical user interface
  convert   - Convert track between formats
  analyze   - Analyze track and display statistics
  optimize  - Automatically optimize speed and turning parameters
  adjust    - Adjust braking points before turns
  help      - Display this help message

File Arguments:
  --input, -i   - Input file path
  --output, -o  - Output file path (required for convert)
  --format, -f  - Override output format (csv, rec, obj, dxf)

Options:
  --brake-points, -b  - Number of braking points before turns (default: 2)
  --debug             - Enable debug output

Examples:
  # Launch GUI with optional file to open
  python ai_track_tool.py gui [track]

  # Convert REC to CSV
  python ai_track_tool.py convert -i rec -o track.csv

  # Analyze a track
  python ai_track_tool.py analyze -i track.csv

  # Optimize and save
  python ai_track_tool.py optimize -i track.csv -o optimized.csv

  # Adjust braking points with 3 points before each turn
  python ai_track_tool.py adjust -i track.csv -o adjusted.csv -b 3
"""
    print(help_text)


def main():
    parser = argparse.ArgumentParser(description='AI Track Tool for Racing Games')
    
    # Main commands
    parser.add_argument('command', choices=['gui', 'convert', 'analyze', 'optimize', 'adjust', 'help'],
                       help='Command to execute')
    
    # Optional input file for GUI mode
    parser.add_argument('file', nargs='?', default=None,
                       help='Optional input file for GUI mode')
    
    # File arguments
    parser.add_argument('--input', '-i', help='Input file path')
    parser.add_argument('--output', '-o', help='Output file path')
    parser.add_argument('--format', '-f', choices=['csv', 'rec', 'obj', 'dxf'],
                       help='Output format (default based on file extension)')
    
    # Options
    parser.add_argument('--brake-points', '-b', type=int, default=2,
                       help='Number of braking points before turns (default: 2)')
    parser.add_argument('--debug', action='store_true', help='Enable debug output')
    
    args = parser.parse_args()
    
    if args.command == 'gui':
        run_gui(args.file)
    else:
        run_cli(args)


if __name__ == "__main__":
    main()