"""
AbuLangModule - Complete AbuLang Integration for Python IDLE
Enables all AbuLang commands and syntax in Python environment
"""

import builtins
import sys
import os
import yaml
from pathlib import Path
from .syntax_fixer import fix_abulang_syntax
from .gui_manager import GUIManager, obj, draw, rgb
from .lib_3d import Scene3D, Object3D, create_3d_scene

__version__ = "4.4.0"
__author__ = "Abu"

# Store original builtins
_original_builtins = {}

# Storage for multi-format blocks and local variables
_current_format = None
_format_buffer = []
_local_vars = {}  # Store local variables from functions

def load_commands():
    """Load commands from commands.yaml"""
    # Try multiple locations
    possible_paths = [
        Path(__file__).parent / "commands.yaml",
        Path("essentials/python/commands.yaml"),
        Path("../essentials/python/commands.yaml"),
    ]
    
    for path in possible_paths:
        if path.exists():
            with open(path, 'r') as f:
                data = yaml.safe_load(f)
                return data.get('commands', {})
    
    return {}

def enable_abulang():
    """
    Enable ALL AbuLang commands in Python IDLE
    Makes AbuLang syntax work natively in Python
    """
    print("[AbuLang] Initializing AbuLang Module...")
    
    # Import necessary modules
    import math
    import statistics
    import time
    import logging
    import socket
    import requests
    
    # Save original input function before overriding
    _original_input = builtins.input
    
    # === BASIC I/O ===
    def show(*args, **kwargs):
        """AbuLang show command - display output"""
        print(*args, **kwargs)
    
    def ask(prompt=""):
        """AbuLang ask command - get user input"""
        return _original_input(str(prompt))
    
    # === IMPORTS ===
    def libra(module_name):
        """AbuLang libra command - import library"""
        # Module name mappings for AbuLang-friendly names
        module_mappings = {
            "UI": "tkinter",
            "ui": "tkinter",
            "DISPLAY": "pygame",
            "ds": "pygame",
            "arrow": "turtle",
            "ar": "turtle",
            "maths": "math",
            "stat": "statistics",
            "osys": "os",
            "req": "requests",
            "web": "requests",
            "jsons": "json",
            "path": "pathlib",
        }
        
        try:
            # Handle special AbuLang packages
            if module_name == "AbuSmart":
                from . import abu_smart
                builtins.smart = abu_smart
                print(f"[AbuLang] Imported AbuSmart as 'smart'")
            elif module_name == "AbuFILES":
                from . import abu_files
                builtins.files = abu_files
                print(f"[AbuLang] Imported AbuFILES as 'files'")
            elif module_name == "AbuINSTALL":
                from . import abu_install
                builtins.installer = abu_install
                print(f"[AbuLang] Imported AbuINSTALL as 'installer'")
            elif module_name == "AbuChess":
                from . import abu_chess
                builtins.chess = abu_chess
                print(f"[AbuLang] Imported AbuChess as 'chess'")
            else:
                # Check if it's a mapped name
                actual_module = module_mappings.get(module_name, module_name)
                
                # Import the module
                module = __import__(actual_module)
                
                # Store with the AbuLang name
                if module_name == "UI" or module_name == "ui":
                    builtins.ui = module
                    print(f"[AbuLang] Imported tkinter as 'ui'")
                elif module_name == "DISPLAY" or module_name == "ds":
                    builtins.ds = module
                    print(f"[AbuLang] Imported pygame as 'ds'")
                elif module_name == "arrow" or module_name == "ar":
                    builtins.ar = module
                    print(f"[AbuLang] Imported turtle as 'ar'")
                else:
                    builtins.__dict__[module_name] = module
                    print(f"[AbuLang] Imported {actual_module}")
        except ImportError as e:
            print(f"[AbuLang] Could not import {module_name}: {e}")
            if module_name in ["UI", "ui"]:
                print(f"[AbuLang] Tip: tkinter should be included with Python")
            elif module_name in ["DISPLAY", "ds"]:
                print(f"[AbuLang] Tip: Install pygame with: pip install pygame")
            elif module_name in ["req", "web"]:
                print(f"[AbuLang] Tip: Install requests with: pip install requests")
    
    # === STRUCTURE / DEFINITION ===
    class defin:
        """AbuLang defin command - define function"""
        def __init__(self, func):
            self.func = func
        def __call__(self, *args, **kwargs):
            return self.func(*args, **kwargs)
    
    define = defin  # Alias
    
    # === DATA HANDLING ===
    def setva(var_name, value):
        """Set variable value"""
        frame = sys._getframe(1)
        frame.f_globals[var_name] = value
    
    def delet(var_name):
        """Delete variable"""
        frame = sys._getframe(1)
        if var_name in frame.f_globals:
            del frame.f_globals[var_name]
    
    # === MATH OPERATIONS ===
    def plus(a, b):
        """Add two numbers"""
        return a + b
    
    def minus(a, b):
        """Subtract two numbers"""
        return a - b
    
    def multi(a, b):
        """Multiply two numbers"""
        return a * b
    
    def divid(a, b):
        """Divide two numbers"""
        return a / b
    
    def expon(a, b):
        """Exponentiation"""
        return a ** b
    
    def modul(a, b):
        """Modulo"""
        return a % b
    
    def absof(x):
        """Absolute value"""
        return abs(x)
    
    def sumup(data):
        """Sum of list"""
        return sum(data)
    
    def avera(data):
        """Average of list"""
        return sum(data) / len(data)
    
    # === STRING OPERATIONS ===
    def strip(text):
        """Trim spaces"""
        return str(text).strip()
    
    def lower(text):
        """Lowercase"""
        return str(text).lower()
    
    def upper(text):
        """Uppercase"""
        return str(text).upper()
    
    def replc(text, old, new):
        """Replace text"""
        return str(text).replace(old, new)
    
    def findt(text, word):
        """Find substring"""
        return str(text).find(word)
    
    def lengt(text):
        """Length of string/list"""
        return len(text)
    
    # === SYSTEM OPERATIONS ===
    def pausi(seconds):
        """Pause for seconds"""
        time.sleep(seconds)
    
    def exitp():
        """Exit program"""
        sys.exit()
    
    # === FILE OPERATIONS ===
    def readf(filename):
        """Read file contents"""
        with open(filename, 'r') as f:
            return f.read()
    
    def write(filename, text):
        """Write to file"""
        with open(filename, 'w') as f:
            f.write(text)
    
    def get_line(line_num, filename):
        """Get specific line from file (1-indexed)"""
        with open(filename, 'r') as f:
            lines = f.readlines()
            if 1 <= line_num <= len(lines):
                return lines[line_num - 1].rstrip('\n')
            return None
    
    def save_as(filename):
        """Save current format buffer to file"""
        global _format_buffer
        if _format_buffer:
            with open(filename, 'w') as f:
                f.write('\n'.join(_format_buffer))
            _format_buffer = []
            return filename
        return None
    
    # === MULTI-FORMAT SUPPORT ===
    class FormatContext:
        """Context manager for multi-format blocks"""
        def __init__(self, format_type):
            self.format_type = format_type
            
        def __enter__(self):
            global _current_format, _format_buffer
            _current_format = self.format_type
            _format_buffer = []
            return self
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            global _current_format
            _current_format = None
            return False
        
        def add(self, line):
            """Add line to format buffer"""
            _format_buffer.append(str(line))
    
    def switch(format_type):
        """Switch to a different format (yaml, json, csv, etc.)"""
        return FormatContext(format_type)
    
    # === INVERSE WALRUS OPERATOR =: ===
    class CompareAssign:
        """Implements the =: operator (assign and compare)"""
        def __init__(self, value):
            self.value = value
        
        def __eq__(self, other):
            # Assign to caller's scope
            frame = sys._getframe(1)
            # Find the variable name being assigned
            import inspect
            code = frame.f_code
            # This is a simplified version - in real use, parse the line
            return self.value
        
        def compare_to(self, var_name, other_value):
            """Compare and assign: x =: 2*y assigns x=2*y and shows comparison"""
            frame = sys._getframe(2)
            frame.f_globals[var_name] = self.value
            
            if self.value < other_value:
                show(f"{var_name}<{other_value} {self.value}")
            elif self.value > other_value:
                show(f"{var_name}>{other_value} {self.value}")
            else:
                show(f"{var_name}=={other_value} {self.value}")
            
            return self.value
    
    def assign_compare(var_name, value, compare_to):
        """
        Inverse walrus: assigns and immediately compares
        Usage: assign_compare('x', 2*y, y) 
        Assigns x=2*y and shows x<y or x>y or x==y
        """
        frame = sys._getframe(1)
        frame.f_globals[var_name] = value
        
        if value < compare_to:
            show(f"{var_name}<{compare_to} {value}")
        elif value > compare_to:
            show(f"{var_name}>{compare_to} {value}")
        else:
            show(f"{var_name}=={compare_to} {value}")
        
        return value
    
    # === STRING INDEXING / FILTERING ===
    def isolate(filter_str, from_list):
        """
        Filter list to only include items containing the filter string
        Usage: isolate("abc", ["abc123", "def456", "abc789"]) -> ["abc123", "abc789"]
        """
        if isinstance(from_list, list):
            return [item for item in from_list if filter_str in str(item)]
        elif isinstance(from_list, str):
            # If it's a string, return characters that match
            return ''.join([char for char in from_list if char in filter_str])
        return []
    
    # === LOCAL VARIABLE MANAGEMENT ===
    class LocalArrow:
        """Implements the -> operator for local variable access"""
        def __init__(self, source):
            self.source = source
        
        def __gt__(self, target):
            # This gets called for ->
            # But we need custom handling
            return (self.source, target)
    
    def local(func_name):
        """
        Access local variables from a function
        Usage: local("my_func").dx returns the value of dx from my_func
        """
        class LocalAccessor:
            def __init__(self, func_name):
                self.func_name = func_name
            
            def __getattr__(self, var_name):
                key = f"{self.func_name}.{var_name}"
                if key in _local_vars:
                    return _local_vars[key]
                raise AttributeError(f"No local variable '{var_name}' in function '{self.func_name}'")
            
            def __setattr__(self, var_name, value):
                if var_name == 'func_name':
                    object.__setattr__(self, var_name, value)
                else:
                    key = f"{self.func_name}.{var_name}"
                    _local_vars[key] = value
        
        return LocalAccessor(func_name)
    
    def local_to_global(func_name, var_name):
        """
        Pull a local variable from a function to global scope
        Usage: local_to_global("my_func", "dx")
        Alternative syntax support: local->global("my_func", "dx")
        """
        key = f"{func_name}.{var_name}"
        if key in _local_vars:
            frame = sys._getframe(1)
            frame.f_globals[var_name] = _local_vars[key]
            return _local_vars[key]
        raise ValueError(f"No local variable '{var_name}' in function '{func_name}'")
    
    def save_local(func_name, var_name, value):
        """Save a local variable for later access"""
        key = f"{func_name}.{var_name}"
        _local_vars[key] = value
    
    # === TEXT MATCHING ===
    def match(arg, kwarg):
        """Match text case based on pattern"""
        if kwarg == kwarg.lower():
            arg = arg.lower()
            print(arg)
        elif kwarg == kwarg.upper():
            arg = arg.upper()
            print(arg)
        else:
            raise ValueError("That does not match our pattern")
        return arg
    
    # === CIPHER ===
    def cipher(arg, kwarg):
        """
        Cipher function with multiple encoding modes
        - Uppercase letters: cycle forward by 1 (A->B, Z->A)
        - Lowercase letters: cycle backward by 1 (a->z, z->y)
        - Int in kwarg: insert QWERTY pattern between letters
        - Float in kwarg: scramble words (middle->first, first->last, random spacing)
        
        Examples:
            cipher("Hi", "hY75") -> "wHwqwiwqw"
            cipher("ABC", "UP") -> "BCD"
            cipher("abc", "low") -> "zab"
            cipher("Hello World", 3.14) -> scrambled with random spacing
        """
        import random
        
        qwerty = "qwertyuiopasdfghjklzxcvbnm"
        has_int = any(c.isdigit() for c in str(kwarg))
        has_float = isinstance(kwarg, float) or ('.' in str(kwarg))
        
        # Handle float type: scramble words
        if has_float:
            # Split by spaces and newlines
            words = arg.split()
            scrambled_words = []
            
            for word in words:
                if len(word) <= 1:
                    scrambled_words.append(word)
                else:
                    # Move middle to first, first to last
                    mid = len(word) // 2
                    first_char = word[0]
                    middle_char = word[mid]
                    last_char = word[-1]
                    
                    # Rearrange: middle -> first, first -> last, rest stays
                    middle_first = middle_char + word[1:mid] + word[mid+1:-1] + first_char
                    scrambled_words.append(middle_first)
            
            # Join with random spacing (1-3 spaces or newlines)
            result_parts = []
            for i, word in enumerate(scrambled_words):
                result_parts.append(word)
                if i < len(scrambled_words) - 1:
                    # Random spacing: spaces or newline
                    spacing_choice = random.choice(['spaces', 'newline'])
                    if spacing_choice == 'newline':
                        result_parts.append('\n')
                    else:
                        result_parts.append(' ' * random.randint(1, 3))
            
            output = ''.join(result_parts)
            print(output)
            return output
        
        # Handle int type: insert QWERTY letters
        result = []
        for char in arg:
            if char.isupper():
                # Uppercase: cycle forward by 1
                if char == 'Z':
                    result.append('A')
                else:
                    result.append(chr(ord(char) + 1))
            elif char.islower():
                # Lowercase: cycle backward by 1
                if char == 'a':
                    result.append('z')
                else:
                    result.append(chr(ord(char) - 1))
            else:
                # Non-letter characters stay the same
                result.append(char)
            
            # If kwarg contains int, insert QWERTY letter after each character
            if has_int:
                qwerty_idx = sum(ord(c) for c in str(kwarg) if c.isdigit()) % len(qwerty)
                result.append(qwerty[qwerty_idx])
        
        output = ''.join(result)
        print(output)
        return output
    
    # === DECIPHER ===
    def decipher(arg, kwarg=None):
        """
        Decipher function - reverses cipher encoding
        - Uppercase letters: cycle backward by 1 (B->A, A->Z)
        - Lowercase letters: cycle forward by 1 (z->a, y->z)
        - Removes QWERTY pattern letters if int was used
        - Unscrambles words if float was used
        
        Examples:
            decipher("BCD") -> "ABC"
            decipher("zab") -> "abc"
        """
        qwerty = "qwertyuiopasdfghjklzxcvbnm"
        result = []
        
        for char in arg:
            if char.isupper():
                # Uppercase: cycle backward by 1
                if char == 'A':
                    result.append('Z')
                else:
                    result.append(chr(ord(char) - 1))
            elif char.islower():
                # Lowercase: cycle forward by 1
                if char == 'z':
                    result.append('a')
                else:
                    result.append(chr(ord(char) + 1))
            else:
                # Non-letter characters stay the same
                result.append(char)
        
        output = ''.join(result)
        print(output)
        return output
    
    # === WEB COMMANDS ===
    def playground():
        """Open AbuLang playground on surge.sh"""
        import webbrowser
        url = "https://abulang.surge.sh"
        webbrowser.open(url)
        print(f"[AbuLang] Opening playground: {url}")
        return url
    
    def fetch(search_term):
        """
        Fetch - search on Google
        Replaces spaces with + and opens Google search
        
        Usage:
            fetch("python tutorial")
            fetch "machine learning"
        """
        import webbrowser
        # Replace spaces with +
        query = str(search_term).replace(" ", "+")
        url = f"https://www.google.com/search?q={query}"
        webbrowser.open(url)
        print(f"[AbuLang] Searching: {search_term}")
        return url
    
    # Create a google search object
    class GoogleSearch:
        """Google search helper"""
        def search(self, query):
            """Search on Google"""
            import webbrowser
            query_str = str(query).replace(" ", "+")
            url = f"https://www.google.com/search?q={query_str}"
            webbrowser.open(url)
            print(f"[AbuLang] Google search: {query}")
            return url
    
    google = GoogleSearch()
    
    # === GUI MANAGER ===
    def gui_create(width=800, height=600, title="AbuLang GUI"):
        """Create a new GUI manager"""
        manager = GUIManager(width, height, title)
        print(f"[AbuLang] Created GUI: {title} ({width}x{height})")
        return manager
    
    def obj_create(manager, shape, top_left, bottom_right):
        """Create an object on the GUI manager"""
        if not isinstance(manager, GUIManager):
            raise TypeError("First argument must be a GUIManager")
        return manager.obj_create(shape, top_left, bottom_right)
    
    def opposite_x(item):
        """Create reflection across X axis"""
        if isinstance(item, obj):
            return item.opposite_x()
        elif isinstance(item, draw):
            return item.opposite_x()
        else:
            raise TypeError("opposite_x requires obj or draw instance")
    
    def opposite_y(item):
        """Create reflection across Y axis"""
        if isinstance(item, obj):
            return item.opposite_y()
        elif isinstance(item, draw):
            return item.opposite_y()
        else:
            raise TypeError("opposite_y requires obj or draw instance")
    
    def assign_obj(drawing_item):
        """Assign a draw to an obj"""
        if not isinstance(drawing_item, draw):
            raise TypeError("assign_obj requires a draw instance")
        return drawing_item
    
    def assign_draw(obj_item):
        """Assign an obj to a draw"""
        if not isinstance(obj_item, obj):
            raise TypeError("assign_draw requires an obj instance")
        return obj_item
    
    def lib_3d():
        """Import 3D library"""
        return create_3d_scene
    
    # === ARROW OPERATOR -> ===
    class Arrow:
        """
        Implements -> operator for local->global
        Usage: Arrow("func_name") -> "var_name" pulls local to global
        """
        def __init__(self, func_name):
            self.func_name = func_name
        
        def __rshift__(self, target):
            """Handle >> as -> operator"""
            if isinstance(target, str):
                return local_to_global(self.func_name, target)
            elif hasattr(target, '__name__') and target.__name__ == 'global':
                # Return a callable that takes var_name
                def pull_to_global(var_name):
                    return local_to_global(self.func_name, var_name)
                return pull_to_global
            return None
    
    # Create a special 'global' marker for local->global syntax
    class GlobalMarker:
        def __call__(self, var_name):
            # This is called when used as local->global("var")
            pass
    
    global_marker = GlobalMarker()
    
    # Add all commands to builtins
    commands = {
        # I/O
        'show': show,
        'ask': ask,
        'input': ask,
        'displ': show,
        
        # Imports
        'libra': libra,
        'library': libra,
        
        # Structure
        'defin': defin,
        'define': define,
        
        # Data
        'setva': setva,
        'assign': setva,
        'delet': delet,
        'remove': delet,
        
        # Math
        'plus': plus,
        'minus': minus,
        'multi': multi,
        'divid': divid,
        'expon': expon,
        'modul': modul,
        'absof': absof,
        'sumup': sumup,
        'avera': avera,
        'mean': avera,
        
        # Strings
        'strip': strip,
        'trim': strip,
        'lower': lower,
        'upper': upper,
        'replc': replc,
        'replace': replc,
        'findt': findt,
        'search': findt,
        'lengt': lengt,
        'count': lengt,
        'isolate': isolate,
        
        # System
        'pausi': pausi,
        'wait': pausi,
        'exitp': exitp,
        'exit': exitp,
        'quit': exitp,
        
        # File
        'readf': readf,
        'readfile': readf,
        'write': write,
        'writi': write,
        'get_line': get_line,
        'save_as': save_as,
        
        # Multi-format
        'switch': switch,
        
        # Advanced operators
        'assign_compare': assign_compare,
        'CompareAssign': CompareAssign,
        
        # Local variables
        'local': local,
        'local_to_global': local_to_global,
        'save_local': save_local,
        'Arrow': Arrow,
        'global_marker': global_marker,
        
        # Text matching
        'match': match,
        'cipher': cipher,
        'decipher': decipher,
        
        # Web commands
        'playground': playground,
        'fetch': fetch,
        'google': google,
        
        # GUI Manager
        'gui_create': gui_create,
        'obj_create': obj_create,
        'obj': obj,
        'draw': draw,
        'GUIManager': GUIManager,
        'rgb': rgb,
        'opposite_x': opposite_x,
        'opposite_y': opposite_y,
        'assign_obj': assign_obj,
        'assign_draw': assign_draw,
        'lib_3d': lib_3d,
    }
    
    # Add to builtins
    for name, func in commands.items():
        if name not in _original_builtins:
            _original_builtins[name] = builtins.__dict__.get(name)
        builtins.__dict__[name] = func
    
    # Also add help_abulang to builtins
    if 'help_abulang' not in _original_builtins:
        _original_builtins['help_abulang'] = builtins.__dict__.get('help_abulang')
    builtins.__dict__['help_abulang'] = help_abulang
    
    print("[AbuLang] ✓ Enabled!")
    print("[AbuLang] Available commands:")
    print("  I/O: show, ask, input")
    print("  Import: libra, library")
    print("  Math: plus, minus, multi, divid, expon, modul, absof, sumup, avera")
    print("  String: strip, lower, upper, replc, findt, lengt, isolate")
    print("  System: pausi, exitp")
    print("  File: readf, write, get_line, save_as")
    print("  Advanced: switch, assign_compare, local, local_to_global")
    print("\nType 'help_abulang()' for full command list")

def exec_abulang(code: str):
    """
    Execute AbuLang code with Python 2 style syntax support
    
    Usage:
        exec_abulang('''
            show "Hello, World!"
            name = ask "What is your name?"
            show "Nice to meet you, " + name
        ''')
    """
    # Fix AbuLang syntax
    fixed_code = fix_abulang_syntax(code)
    
    # Execute the fixed code
    frame = sys._getframe(1)
    exec(fixed_code, frame.f_globals, frame.f_locals)

def disable_abulang():
    """Disable AbuLang and restore original builtins"""
    for name, original in _original_builtins.items():
        if original is None:
            if name in builtins.__dict__:
                del builtins.__dict__[name]
        else:
            builtins.__dict__[name] = original
    _original_builtins.clear()
    print("[AbuLang] Disabled")

def help_abulang():
    """Show all available AbuLang commands"""
    print("""
=== AbuLang Commands ===

I/O Commands:
  show(...)       - Display output
  ask(prompt)     - Get user input
  
Import Commands:
  libra(module)   - Import library
  
Math Commands:
  plus(a, b)      - Add numbers
  minus(a, b)     - Subtract numbers
  multi(a, b)     - Multiply numbers
  divid(a, b)     - Divide numbers
  expon(a, b)     - Power (a^b)
  modul(a, b)     - Modulo (a%b)
  absof(x)        - Absolute value
  sumup(list)     - Sum of list
  avera(list)     - Average of list
  
String Commands:
  strip(text)     - Remove spaces
  lower(text)     - Lowercase
  upper(text)     - Uppercase
  replc(t,o,n)    - Replace text
  findt(text,w)   - Find substring
  lengt(text)     - Length
  isolate(str, list) - Filter list by string
  
System Commands:
  pausi(seconds)  - Pause/sleep
  exitp()         - Exit program
  
File Commands:
  readf(file)        - Read file
  write(file,txt)    - Write file
  get_line(n, file)  - Get line N from file
  save_as(file)      - Save format buffer to file

Multi-Format Commands:
  switch(format)     - Switch format (yaml, json, csv)
  save_as(file)      - Save current buffer

Advanced Operators:
  assign_compare(var, val, cmp) - Assign and compare (=: operator)
    Example: assign_compare('x', 2*y, y)
    Assigns x=2*y and shows "x<y 12" or "x>y 12"
  
Local Variable Management:
  local(func)           - Access local vars from function
    Example: dx = local("my_func").dx
  
  local_to_global(func, var) - Pull local to global
    Example: local_to_global("my_func", "dx")
  
  save_local(func, var, val) - Save local variable
    Example: save_local("my_func", "dx", 4)

Text Matching:
  match(text, pattern) - Match text case to pattern
    If pattern is lowercase, converts text to lowercase
    If pattern is uppercase, converts text to uppercase
    Raises error for mixed case patterns
    Example: match("Hello", "test") -> "hello"
    Example: match("Hello", "TEST") -> "HELLO"

  cipher(text, pattern) - Encode text with cipher
    Uppercase letters: cycle forward by 1 (A->B, Z->A)
    Lowercase letters: cycle backward by 1 (a->z, z->y)
    If pattern contains digits: insert QWERTY letters between each character
    If pattern is float: scramble words (middle->first, first->last, random spacing/newlines)
    Example: cipher("Hi", "hY75") -> "wHwqwiwqw"
    Example: cipher("ABC", "UP") -> "BCD"
    Example: cipher("abc", "low") -> "zab"
    Example: cipher("Hello World", 3.14) -> scrambled with random spacing

  decipher(text) - Decode cipher text
    Reverses cipher encoding
    Example: decipher("BCD") -> "ABC"
    Example: decipher("zab") -> "abc"

Web Commands:
  playground() - Open AbuLang playground on surge.sh
    Example: playground()
  
  fetch(search) - Search on Google
    Replaces spaces with + and opens Google search
    Example: fetch("python tutorial")
    Example: fetch "machine learning"
  
  google.search(query) - Google search helper
    Example: google.search("AI programming")

GUI Manager:
  gui_create(width, height, title) - Create a new GUI manager
    Returns a GUIManager instance
    Example: gui = gui_create(800, 600, "My App")
  
  obj_create(manager, shape, top_left, bottom_right) - Create an object
    Shapes: 'rect', 'circle', 'line', 'polygon', 'text'
    Example: obj = obj_create(gui, 'rect', (10, 10), (100, 100))
  
  obj class - Animated object
    Methods: draw(), move(dx, dy), set_color(fill, outline), animate(duration, callback)
    Methods: velocity(dx, dy), tp(coords), teleport(coords), opposite_x(), opposite_y()
    Properties: shape, x1, y1, x2, y2, fill_color, outline_color, visible, velocity_x, velocity_y
  
  draw class - Drawing layer
    Methods: line(x1, y1, x2, y2), rect(x1, y1, x2, y2), circle(x1, y1, x2, y2)
    Methods: text(x, y, text), polygon(coords), clear(), opposite_x(), opposite_y()
    Example: d = gui.get_draw(); d.line(0, 0, 100, 100)
  
  rgb(r, g, b) - Convert RGB to hex color
    Example: rgb(255, 0, 0) -> "#ff0000"
  
  opposite_x(item) - Reflect obj or draw across X axis
    Example: reflected = opposite_x(my_obj)
  
  opposite_y(item) - Reflect obj or draw across Y axis
    Example: reflected = opposite_y(my_draw)
  
  assign_obj(draw) - Assign draw to obj
  assign_draw(obj) - Assign obj to draw
  
  lib_3d() - Import 3D library (Ursina/Panda3D)
    Example: scene = lib_3d()("My 3D Scene")
    Methods: create_cube(), create_sphere(), create_model(), set_camera(), run()

String Filtering:
  isolate(filter, list) - Keep only items containing filter
    Example: isolate("abc", ["abc1", "def2", "abc3"]) -> ["abc1", "abc3"]

GUI Widgets (Tkinter):
  libra("UI")          - Import tkinter as 'ui'
  
  Widgets:
    ui.Tk()            - Main window
    ui.Label()         - Display text
    ui.Button()        - Clickable button
    ui.Entry()         - Text input field (inputbox)
    ui.Canvas()        - Drawing surface
    ui.Scale()         - Slider control
    ui.Checkbutton()   - Checkbox
    ui.OptionMenu()    - Dropdown menu
    ui.Frame()         - Container
    ui.Scrollbar()     - Scrollbar
  
  Layout:
    widget.pack()      - Simple layout (spacex, spacey for padding)
    widget.grid()      - Grid layout (arrange)
    widget.place()     - Absolute positioning
  
  Events:
    onclick = "<Button-1>"   - Mouse click
    onkey = "<Key>"          - Any key press
    ona = "<a>"              - Key 'a' press
    onspace = "<space>"      - Spacebar
    onenter = "<Return>"     - Enter key
    onup/down/left/right     - Arrow keys
  
  Colors:
    red, green, blue, white, black, yellow
  
  Example:
    libra("UI")
    window = ui.Tk()
    window.title("My App")
    btn = ui.Button(window, text="Click")
    btn.pack(spacex=10, spacey=5)
    window.mainloop()

Game Development (Pygame):
  libra("DISPLAY")     - Import pygame as 'ds'
  
  Commands:
    ds.init()          - Initialize pygame (screen)
    ds.display.set_mode() - Create window (makescreen)
    ds.display.flip()  - Update display (refresh)
    ds.draw.circle()   - Draw circle
    ds.draw.rect()     - Draw rectangle
    surface.fill()     - Fill with color
  
  Example:
    libra("DISPLAY")
    ds.init()
    screen = ds.display.set_mode((800, 600))
    screen.fill(black)
    ds.display.flip()

AbuLang Packages:
  libra("AbuSmart")    - System utilities
  libra("AbuFILES")    - File operations
  libra("AbuINSTALL")  - Package manager
  libra("AbuChess")    - Chess AI

Keyboard Event Aliases:
  ona, onb, onc, ond, one, onf, ong, onh, oni, onj, onk, onl, onm,
  onn, ono, onp, onq, onr, ons, ont, onu, onv, onw, onx, ony, onz
  onspace, onenter, onescape, onup, ondown, onleft, onright

Note: In IDLE, you must use parentheses: show("text")
For no-parentheses syntax, use .abu files: python AbuLang.py file.abu

=== AbuLang Interpreter (v4.2+) ===

The interpreter allows Python 2 style syntax for AbuLang commands:
  python -m AbuLangModule.interpreter script.py

WHAT IT CAN HANDLE:
  ✓ Commands at line start: show "text"
  ✓ Commands in assignments: name = ask "prompt"
  ✓ Commands with parentheses: show("text")
  ✓ Multi-arg with parentheses: plus(x, y)

WHAT IT CANNOT HANDLE (use parentheses instead):
  ✗ Commands with multiple args without parentheses: plus x, y
    → Use: plus(x, y)
  
  ✗ Commands in expressions: show strip "text"
    → Use: show(strip("text"))
  
  ✗ Commands as function arguments: print(ask "prompt")
    → Use: print(ask("prompt"))
  
  ✗ Commands in conditionals: if show "test":
    → Use: if show("test"):
  
  ✗ Commands in collections: [show "a", show "b"]
    → Use: [show("a"), show("b")]
  
  ✗ Chained commands: show strip lower "TEXT"
    → Use: show(strip(lower("TEXT")))

BEST PRACTICES:
  - Use parentheses for multi-argument commands
  - Use parentheses for nested/chained commands
  - Use .abu files for complex programs
  - Use Python syntax for anything beyond simple statements

ERROR HANDLING:
  - Syntax errors show line number and common issues
  - Runtime errors display with full traceback
  - Use help_abulang() for command reference
""")

# Auto-enable on import
enable_abulang()

# Exports
__all__ = [
    'enable_abulang',
    'disable_abulang',
    'help_abulang',
    'exec_abulang',
    'fix_abulang_syntax',
]
