# @yaml
# signature: |-
#   insert <line_number>
#   <text_to_add>
#   end_of_insert
# docstring: inserts the given text after the specified line number in the open file. The text to insert is terminated by a line with only end_of_insert on it. All of the <text_to_add> will be entered, so make sure your indentation is formatted properly. Python files will be checked for syntax errors after the insertion. If the system detects a syntax error, the insertion will not be executed. Simply try to insert again, but make sure to read the error message and modify the insert command you issue accordingly.
# end_name: end_of_insert
# arguments:
#   line_number:
#     type: integer
#     description: the line number after which to insert the text
#     required: true
#   text_to_add:
#     type: string
#     description: the text to insert after the specified line
#     required: true
insert() {
    if [ -z "$CURRENT_FILE" ]
    then
        echo 'No file open. Use the `open` command first.'
        return
    fi

    local line_number="$(echo $1)"

    if [ -z "$line_number" ]
    then
        echo "Usage: insert <line_number>"
        return
    fi

    local re='^[0-9]+$'
    if ! [[ $line_number =~ $re ]]; then
        echo "Usage: insert <line_number>"
        echo "Error: line_number must be a number"
        return
    fi

    local linter_cmd="flake8 --isolated --select=F821,F822,F831,E111,E112,E113,E999,E902"
    local linter_before_insert=$($linter_cmd "$CURRENT_FILE" 2>&1)

    # Bash array starts at 0, so let's adjust
    local insert_after=$((line_number))

    local line_count=0
    local text_to_add=()
    while IFS= read -r line
    do
        text_to_add+=("$line")
        ((line_count++))
    done

    # Create a backup of the current file
    local parent_dir=$(dirname "$CURRENT_FILE")
    local filename=$(basename "$CURRENT_FILE")
    local backup_file="${parent_dir}/backup_${filename}"

    # Check if file has write permissions
    if [ ! -w "$CURRENT_FILE" ]; then
        echo "Error: You cannot edit read-only file $CURRENT_FILE"
        return 1
    fi

    if ! cp "$CURRENT_FILE" "$backup_file" 2>/dev/null; then
        echo "Error: You cannot edit read-only file $CURRENT_FILE"
        return 1
    fi

    # Read the file line by line into an array
    mapfile -t lines < "$CURRENT_FILE"
    local new_lines=("${lines[@]:0:$insert_after}" "${text_to_add[@]}" "${lines[@]:$insert_after}")
    # Write the new stuff directly back into the original file
    printf "%s\n" "${new_lines[@]}" >| "$CURRENT_FILE"

    # Run linter
    if [[ $CURRENT_FILE == *.py ]]; then
        _lint_output=$($linter_cmd "$CURRENT_FILE" 2>&1)
        lint_output=$(_split_string "$_lint_output" "$linter_before_insert" "$((insert_after+1))" "$((insert_after+line_count))" "$line_count")
    else
        # do nothing
        lint_output=""
    fi

    # if there is no output, then the file is good
    if [ -z "$lint_output" ]; then
        export CURRENT_LINE=$((insert_after + 1))
        _constrain_line
        _print

        echo "File updated. Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary."
    else
        echo "Your proposed insertion has introduced new syntax error(s). Please read this error message carefully and then retry inserting into the file."
        echo ""
        echo "ERRORS:"
        echo "$lint_output"
        echo ""

        # Save original values
        original_current_line=$CURRENT_LINE
        original_window=$WINDOW

        # Update values
        export CURRENT_LINE=$((insert_after + (line_count / 2))) # Set to "center" of insertion
        export WINDOW=$((line_count + 10)) # Show +/- 5 lines around insertion

        echo "This is how your insertion would have looked if applied"
        echo "-------------------------------------------------"
        _constrain_line
        _print
        echo "-------------------------------------------------"
        echo ""

        # Restoring CURRENT_FILE to original contents.
        cp "$backup_file" "$CURRENT_FILE"

        export CURRENT_LINE=$insert_after
        export WINDOW=10

        echo "This is the original code before your insertion"
        echo "-------------------------------------------------"
        _constrain_line
        _print
        echo "-------------------------------------------------"

        # Restore original values
        export CURRENT_LINE=$original_current_line
        export WINDOW=$original_window

        echo "Your changes have NOT been applied. Please fix your insert command and try again."
        echo "You either need to 1) Specify the correct line number argument or 2) Correct your insertion code."
        echo "DO NOT re-run the same failed insert command. Running it again will lead to the same error."
    fi

    # Remove backup file
    rm -f "$backup_file"
}
