import sys
import os
import argparse 

# Import all the necessary classes from your 'core.py' file
# ChotuSyntaxError is added for better error handling in REPL
from .core import Lexer, Parser, Interpreter, ChotuFunction, ChotuRuntimeError, ChotuSyntaxError
CHOTULANG_VERSION: str = "0.0.7"
CHOTULANG_OWNER: str = "Vishnu Deviprasad Shetty"
PASTE_TRIGGER: str = '--'

# --- Documentation String (UPDATED to Version 2.5.1) ---
# This is the full documentation, stored in a string to be printed by 'help'
CHOTULANG_DOCUMENTATION = """
=========================================
 Chotulang Software License (v{CHOTULANG_VERSION})
=========================================
All rights reserved. This software is proprietary and is the sole property of
{CHOTULANG_OWNER}.

Unauthorized copying, distribution, or modification of this software, or any 
portion of it, is strictly prohibited. Use of this software is subject to 
the terms of the end-user license agreement (EULA) provided by the owner.

Copyright (c) 2024 {CHOTULANG_OWNER}.
"""

# --- Full Documentation String (The Chotulang Development Guide) ---
# This string contains the full guide requested by the user.
CHOTULANG_DOCUMENTATION: str = f"""
==========================================
CHOTULANG DEVELOPMENT GUIDE (Version {CHOTULANG_VERSION})
==========================================

Chotulang is a dynamic, Python-compatible language that emphasizes clean, readable syntax and supports powerful functional features like pipes and lambdas.

----------------------------
MODULE 1: CORE FUNDAMENTALS
----------------------------

1. PRINTING AND VARIABLES
Use 'out' to print. Use 'var' to declare a variable.

var name = "Alex"      // String
var count = 5          // Number
var is_active = true   // Boolean

out "Hello,", name, "!"
out "The value is:", count

// User Input
out "Enter a number:"
var user_input = ask() // Reads a line of text
out "You entered:", user_input

2. COMMENTS
Use the '#' symbol for comments.

# This line is ignored by the interpreter

----------------------------
MODULE 2: OPERATOR PRECEDENCE
----------------------------

Understanding the order of operations ensures your calculations are correct.

| Precedence | Operator | Description | Example |
| :--- | :--- | :--- | :--- |
| Highest | () | Parentheses (Forces order) | `(5 + 2) * 3` |
| 2 | ** | Power/Exponent (Right-associative) | `2 ** 3 ** 2` is `2 ** (3 ** 2)` (512) |
| 3 | *, /, % | Multiplication, Division, Modulo | `10 / 2 * 5` (Left-to-right) |
| 4 | +, - | Addition, Subtraction | `3 + 4 - 1` (Left-to-right) |
| 5 | <, >, ==, !=| Comparison | `x > 5` |
| 6 | &&, || | Logical AND, OR | `true && false` |
| Lowest | =, +=, -=, *=, /= | Assignment | `x = 10` |

// Power Operator Example (Exponent)
var result_power = 8 ** 2
out "8 squared is:", result_power // 64

var complex_calc = 10 - 2 ** 3 * 2
// Order: 2**3 (8), then 8*2 (16), then 10-16 (-6)
out "Complex calculation:", complex_calc

----------------------------
MODULE 3: CONTROL FLOW & LOOP JUMPS
----------------------------

1. IF/ELSE STATEMENTS
Conditional execution blocks. The curly braces {{}} are mandatory.

var temperature = 30

if temperature > 25 {{
    out "It is hot."
}} else {{
    out "It is mild."
}}

2. LOOPS (ITERATION)

// The 'do' Loop (Similar to While)
var i = 0
do i < 3 {{
    out "Do loop iteration:", i
    i += 1
}}

// The 'for' Loop (Iterates over a list or range)
for number in 0..4 {{
    out "Current number:", number
}}

3. LOOP JUMP STATEMENTS

// WARNING: These must only be used **inside** a 'do' or 'for' loop!

// 'break'
// Stops the current loop entirely and execution continues after the loop.
do true {{
    out "Running once..."
    break // Exits the 'do' loop
}}

// 'next'
// Skips the rest of the code in the current loop body and starts the next iteration.
for i in 1..5 {{
    if i == 3 {{
        next // Skip printing 3, go straight to 4
    }}
    out "Number:", i
}}


----------------------------
MODULE 4: DATA STRUCTURES
----------------------------

1. LISTS (Ordered Collections)

var fruits = ["apple", "banana", "kiwi"]
out fruits[1]          // Access: banana
fruits.append("grape") // Add to end

2. DICTIONARIES (Key-Value Pairs)

var user = {{
    "id": 101,
    "status": "online"
}}

out user["status"]     // Access: online
user.set("city", "London") // Add/Update a key

----------------------------
MODULE 5: FUNCTIONS AND PIPES
----------------------------

1. STANDARD FUNCTIONS ('fn')
Use 'fn' for reusable code blocks. Use 'ret' to return a value.

fn multiply(x, y) {{
    ret x * y
}}

var product = multiply(8, 6)
out "Product:", product

2. LAMBDA FUNCTIONS (Anonymous Functions)

// Syntax: fn(params) => expression
var is_even = fn(n) => n % 2 == 0
out is_even(4) // true

3. THE PIPE OPERATOR (`|>`)
Pass the result of one expression as the first argument to the next function.

fn increment(x) {{ ret x + 1 }}
fn double(x) {{ ret x * 2 }}

var value = 10 |> increment |> double // (10 + 1) * 2 = 22
out value

----------------------------
MODULE 6: COMPLEX MATHEMATICAL OPERATIONS
----------------------------

1. USING THE PYTHON MATH LIBRARY
Import the standard Python 'math' module using the 'use' keyword.

use math

// Square Root
var root = math.sqrt(64)
out "Root of 64:", root

// Trigonometry and Constants
var angle = math.radians(45)
var sine_val = math.sin(angle)
out "Sine of 45 deg:", sine_val
out "Pi value:", math.pi // Access constant

2. COMPLEX CALCULATION WITH PIPES

fn area_calc(r) {{ ret math.pi * r ** 2 }} // Using ** for r squared
fn round_2(n) {{ ret round(n, 2) }}

var r = 5
var final_area = r |> area_calc |> round_2 // 5 -> area_calc -> round_2
out "Rounded Area:", final_area

----------------------------
PRACTICE PROJECTS
----------------------------

1. THE GUESSING GAME
Use the 'random' library (`use random`). Generate a random number. Use a 'do' loop and 'if/else' to let the user guess until correct, providing 'Too High' or 'Too Low' hints.

2. MATH & DATA PIPELINE
Create a list of numbers. Use `map` (or a loop) and a lambda to cube every number, then use the pipe operator to feed the resulting list to a function that calculates the sum of all elements.

3. GEOMETRY FUNCTION
Write a function that accepts two numbers (A and B). This function must check if A and B are positive numbers. If they are, it uses the 'math' library to calculate the perimeter of a rectangle (2A + 2B) and returns it. If not, it returns the string "Error: Invalid dimensions".

=========================================
 1. CLI Usage
---------------------------------
The interpreter can be run from your terminal.

* `chotulang`
  Starts the Interactive REPL (Read-Eval-Print Loop).

* `chotulang <filename>`
  Executes the specified Chotulang source file (e.g., `my_script.chotu`).

* `chotulang --debug <filename>`
  Executes the file in debug mode, printing Lexer tokens and Parser AST.

* `chotulang -h` or `--help`
  Displays the command-line help message.

* `chotulang -v` or `--version`
  Displays the interpreter version.

* `chotulang --license`
  Displays the software license.

---------------------------------
 2. REPL Meta-Commands
---------------------------------
Inside the REPL, the following commands are available:
(No leading '/' is required)

* `help` (or `docs`)
  Prints this full documentation.

* `clear` (or `cls`)
  Clears the terminal screen.

* `debug`
  Toggles debug mode (Tokens/AST) ON or OFF for the current session.

* `vars`
  Displays all currently defined global variables.

* `load <filename>`
  Loads and executes a .chotu file into the current REPL session.
  Variables and functions from the file will be available to use.
  Example: `load my_functions.chotu`

* `exit` (or `quit`)
  Exits the REPL.

* '{PASTE_TRIGGER} ... {PASTE_TRIGGER}' (Multi-line Paste)
  Enter '{PASTE_TRIGGER}' on a line by itself to start multi-line input.
  Paste or type your code, then enter '{PASTE_TRIGGER}' on a new line to execute.

---------------------------------
 3. Language Keywords & Syntax
---------------------------------
| Category      | Keyword   | Description |
| :------------- | :-------- | :---------- |
| Declaration | `var`     | Declares a mutable variable (e.g., `var x = 10`). |
| Output | `out`     | Prints expressions (e.g., `out "hello", 1 + 2`). |
| Logic | `if`, `else` | Conditional execution (e.g., `if x > 5 {{ ... }} else {{ ... }}`). |
| Loops | `do`      | Defines a 'while' loop (e.g., `do x < 10 {{ ... }}`). |
| Iteration | `for`, `in` | Iterates over an iterable (e.g., `for i in [1,2,3] {{ ... }}`). |
| Flow Control | `break`, `next` | Exits a loop (`break`) or skips to the next iteration (`next`). |
| Functions | `fn`, `ret` | Defines a function (`fn f(a) {{ ... }}`) and returns a value (`ret a * 2`). |
| Lambda | `=>`      | Defines an anonymous function (e.g., `fn(x) => x + 1`). |
| Error Handle | `try`, `catch` | Handles runtime errors (e.g., `try {{ ... }} catch err_var {{ ... }}`). |
| Module | `use`, `as` | Imports Python modules (e.g., `use math as m`). |
| Static Type | `strict`  | Toggles optional static type checking (e.g., `strict true`). |
| Literals | `true`, `false`, `null` | Boolean and null values. |

---------------------------------
 4. Operators
---------------------------------
* Arithmetic: `+`, `-`, `*`, `/`, `%`
* Compound: `+=`, `-=`, `*=`, `/=`, `%=` (e.g., `x += 1`)
* Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`
* Logical: `and`, `or`, `not`
* **Pipe: `|>`** (e.g., `10 |> add_five |> double`)
* Range: `..` (e.g., `1..10` creates a list from 1 to 9)
* Null Coalesce: `??` (e.g., `a ?? "default"`)

---------------------------------
 5. Data Types
---------------------------------
* Numbers: `123`, `45.6`
* Strings: `"hello"`, `'world'`
* Lists: `[1, "two", true]`
* Dicts: `{{"a": 1, "b": 2}}`
* Functions: First-class citizens. They can be assigned to variables and
             passed to other functions.

---------------------------------
 6. Built-in Functions
---------------------------------
* `len()`, `input()`, `type()`, `range()`
* `num()`, `str()`, `bool()`, `list()` (Type conversions)
* `map()`, `filter()`, `reduce()` (Supports Chotulang `fn` types)
* `keys()`, `values()`, `items()`, `sorted()`, `reversed()`
* `read_file()`, `write_file()`, `append_file()`
* `json_parse()`, `json_stringify()`
* `py_import()`, `py_call()`, `py_get()`, `py_set()` (Python Interop)
* ...and many more math/utility functions.

---------------------------------
 7. Method Calls
---------------------------------
* String: `my_str.upper()`, `my_str.lower()`, `my_str.split(',')`
* List: `my_list.append(x)`, `my_list.pop()`, `my_list.sort()`
* Dict: `my_dict.keys()`, `my_dict.values()`, `my_dict.get(key)`

Author: {CHOTULANG_OWNER} (a.k.a idkshetty a.k.a chotu)
"""

def print_help():
    """Prints the formatted documentation."""
    print(CHOTULANG_DOCUMENTATION)

# --- REVISED 'run_code' ---
# Executes code and returns True on success, False on error.
def run_code(interpreter, code, debug=False):
    """
    Tokenizes, parses, and interprets a block of Chotulang code
    using a persistent interpreter.
    
    Returns True on success, False on error.
    """
    try:
        lexer = Lexer(code); tokens = lexer.tokenize()
        if debug: print("Tokens:", tokens)
            
        # IMPORTANT: Pass the source 'code' to the Parser for contextual error reporting
        parser = Parser(tokens, code); ast = parser.parse()
        if debug: print("AST:", ast)
        
        result = interpreter.interpret(ast)
        
        # Print the result of expressions (for REPL)
        if result is not None:
            if isinstance(result, ChotuFunction):
                print(repr(result))
            else:
                print(result)
        return True

    except ChotuSyntaxError as e:
        print(f"Syntax Error: {e}")
        return False
    except Exception as e:
        # ChotuRuntimeError already includes line number if available
        print(f"Error: {e}") 
        return False

# --- ENHANCED CLI: Using argparse and Multi-line Delimiters ---
def main():
    # Setup argument parsing
    parser = argparse.ArgumentParser(
        description="Chotulang Interpreter and REPL (Version 2.5.1).",
        epilog="If no file is provided, the interpreter starts in REPL mode."
    )
    
    parser.add_argument(
        'filename',
        nargs='?', 
        default=None,
        help="Path to the Chotulang source file (.chotu) to execute."
    )
    
    parser.add_argument(
        '-d', '--debug',
        action='store_true',
        help="Enable debug mode, showing Lexer tokens and Parser AST."
    )
    
    args = parser.parse_args()
    
    # Create one interpreter for the whole session
    interpreter = Interpreter()
    
    # --- File Execution Mode ---
    if args.filename:
        filename = args.filename
        if not os.path.exists(filename): 
            print(f"Error: File '{filename}' not found")
            sys.exit(1)
        with open(filename, 'r', encoding='utf-8') as f: 
            code = f.read()
        
        run_code(interpreter, code, debug=args.debug) 
    
    # --- REPL Mode (UPDATED for Multi-line Delimiter) ---
    else:
        print("Chotulang Enhanced REPL (Type 'help' for documentation, 'exit' to quit)")
        debug_mode = args.debug 
        
        code_block = [] 
        pasting_mode = False # State flag for multi-line input
        
        while True:
            try:
                # Set the prompt based on the mode
                prompt = "... " if pasting_mode else "> "
                line = input(prompt)
                
                # --- Handle Pasting Mode ---
                if pasting_mode:
                    if line.strip() == '--':
                        pasting_mode = False
                        full_code = "\n".join(code_block)
                        
                        # Execute the collected block if it's not empty
                        if full_code.strip():
                            run_code(interpreter, full_code, debug=debug_mode)
                        
                        code_block = [] # Reset block
                        continue
                    else:
                        code_block.append(line)
                        continue
                
                # --- Handle Single-Line / Command Mode ---
                
                # Check for multi-line start
                if line.strip() == '--':
                    pasting_mode = True
                    print("--- Pasting mode started (end with '--') ---")
                    continue
                
                # Check for empty line
                if not line.strip():
                    continue

                command = line.strip().lower()

                # --- Handle REPL Meta-Commands (only in single-line mode) ---
                if command in ['exit', 'quit']:
                    break
                
                elif command == 'help':
                    print_help()
                    continue

                elif command in ['clear', 'cls']:
                    os.system('cls' if os.name == 'nt' else 'clear')
                    continue
                
                elif command == 'debug':
                    debug_mode = not debug_mode
                    print(f"Debug mode is now {'ON' if debug_mode else 'OFF'}")
                    continue

                elif command.startswith('load '):
                    filename = line.strip()[5:]
                    if not filename:
                        print("Error: Please specify a filename. Usage: load <filename>")
                        continue
                    if not os.path.exists(filename):
                        print(f"Error: File '{filename}' not found")
                        continue
                    
                    try:
                        with open(filename, 'r', encoding='utf-8') as f:
                            file_code = f.read()
                        print(f"Loading and executing '{filename}'...")
                        run_code(interpreter, file_code, debug=debug_mode)
                    except Exception as e:
                        print(f"Error loading file: {e}")
                    continue
                
                # --- Execute Single-Line Chotulang Code ---
                run_code(interpreter, line, debug=debug_mode) 

            except KeyboardInterrupt: 
                if pasting_mode:
                    print("\n--- Pasting mode cancelled ---")
                    pasting_mode = False
                    code_block = [] 
                else:
                    print("\nBye!"); 
                    break
            except EOFError:
                print("\nBye!")
                break
            except Exception as e: 
                print(f"Internal Error: {e}")
                pasting_mode = False
                code_block = []