// Todo App - Stress tests ADTs, pattern matching, and list operations
//
// This demonstrates:
// - ADTs for data modeling
// - Pattern matching
// - List operations
// - Recursive display

// Todo item
type Priority =
    | Low
    | Medium
    | High

type TodoItem =
    | TodoItem(Int, String, Bool, Priority)

// Helper functions for TodoItem
fn getId(item: TodoItem): Int =
    match item { TodoItem(id, _, _, _) => id }

fn getDescription(item: TodoItem): String =
    match item { TodoItem(_, desc, _, _) => desc }

fn isCompleted(item: TodoItem): Bool =
    match item { TodoItem(_, _, completed, _) => completed }

fn getPriority(item: TodoItem): Priority =
    match item { TodoItem(_, _, _, priority) => priority }

fn setCompleted(item: TodoItem, completed: Bool): TodoItem =
    match item { TodoItem(id, desc, _, priority) => TodoItem(id, desc, completed, priority) }

// Priority helpers
fn priorityToString(p: Priority): String =
    match p {
        Low => "Low",
        Medium => "Medium",
        High => "High"
    }

fn priorityToSymbol(p: Priority): String =
    match p {
        Low => ".",
        Medium => "*",
        High => "!"
    }

// Format a todo item for display
fn formatItem(item: TodoItem): String =
    toString(getId(item)) + ". " + (if isCompleted(item) then "[x]" else "[ ]") + " " + priorityToSymbol(getPriority(item)) + " " + getDescription(item)

// Display functions using recursion
fn printItemsHelper(items: List<TodoItem>): Unit with {Console} =
    match List.head(items) {
        None => (),
        Some(item) => {
            Console.print("  " + formatItem(item))
            match List.tail(items) {
                None => (),
                Some(rest) => printItemsHelper(rest)
            }
        }
    }

fn displayItems(items: List<TodoItem>): Unit with {Console} =
    if List.isEmpty(items) then Console.print("  (no items)")
    else printItemsHelper(items)

fn countCompleted(items: List<TodoItem>): Int =
    List.length(List.filter(items, isCompleted))

fn displayStats(items: List<TodoItem>): Unit with {Console} =
    Console.print("Total: " + toString(List.length(items)) + " | Completed: " + toString(countCompleted(items)) + " | Pending: " + toString(List.length(items) - countCompleted(items)))

// Sample data - all on one line to avoid multiline list parse issues
fn createSampleData(): List<TodoItem> = [TodoItem(1, "Learn Lux basics", true, High), TodoItem(2, "Build a project", false, High), TodoItem(3, "Read documentation", true, Medium), TodoItem(4, "Write tests", false, Medium), TodoItem(5, "Share with team", false, Low)]

// Filter functions
fn filterCompleted(items: List<TodoItem>): List<TodoItem> =
    List.filter(items, isCompleted)

fn filterPending(items: List<TodoItem>): List<TodoItem> =
    List.filter(items, fn(item: TodoItem): Bool => isCompleted(item) == false)

// Main demo
fn main(): Unit with {Console} = {
    Console.print("========================================")
    Console.print("         TODO APP DEMO")
    Console.print("========================================")
    Console.print("")

    let items = createSampleData()

    Console.print("All Todo Items:")
    Console.print("---------------")
    displayItems(items)
    Console.print("")
    displayStats(items)
    Console.print("")

    Console.print("Completed Items:")
    Console.print("----------------")
    displayItems(filterCompleted(items))
    Console.print("")

    Console.print("Pending Items:")
    Console.print("--------------")
    displayItems(filterPending(items))
    Console.print("")

    Console.print("Marking item 2 as complete...")
    let updatedItems = List.map(items, fn(item: TodoItem): TodoItem => if getId(item) == 2 then setCompleted(item, true) else item)
    Console.print("")

    Console.print("Updated Todo List:")
    Console.print("------------------")
    displayItems(updatedItems)
    Console.print("")
    displayStats(updatedItems)
}

let output = run main() with {}
