using Bogus.DataSets;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tumble;
using Tumble.AIStuff;
using static System.Net.Mime.MediaTypeNames;

namespace Tumble
{
    class Worklines
    {
        // Enum to represent the state of a line
        enum LineState
        {
            Ungenerated,    // '~'
            Collapsed,      // '+'
            Expanded        // '-'
        }

        static List<WorkLine> workLines = new List<WorkLine>();
        static int selectedIndex = 0;
        static object lockObj = new object();
        // Keeps track of the Y position for each line
        static List<int> linePositions = new List<int>();

        public static async Task Start()
        {
            var tempVisible = Console.CursorVisible;
            var width = Console.WindowWidth;
            var height = Console.WindowHeight;
            Task.Run(async () =>
            {
                while (true)
                {
                    if (width != Console.WindowWidth || height != Console.WindowHeight)
                    {
                        width = Console.WindowWidth;
                        height = Console.WindowHeight;
                        Render();
                    }
                    await Task.Delay(100);
                }
            });

            Console.CursorVisible = false;
            InitializeWorkLines();

            bool exit = false;
            while (!exit)
            {
                Render();
                var key = Console.ReadKey(true);
                switch (key.Key)
                {
                    case ConsoleKey.UpArrow:
                        if (selectedIndex > 0)
                            selectedIndex--;
                        break;
                    case ConsoleKey.DownArrow:
                        if (selectedIndex < workLines.Count - 1)
                            selectedIndex++;
                        break;
                    case ConsoleKey.Spacebar:
                        await HandleSpace();
                        break;
                    case ConsoleKey.Delete:
                        workLines.RemoveAt(selectedIndex);
                        break;
                    case ConsoleKey.Escape:
                        exit = true;
                        break;
                }
            }

            Console.CursorVisible = tempVisible;
        }

        static void InitializeWorkLines()
        {
            // Initialize with example program
            workLines.Add(new WorkLine("plot the sine function, save the image to desktop as sine.png"));
            workLines.Add(new WorkLine("create a 4x4 grid image of sine.png duplicated 4 times, one in each corner and save it as collage.png"));
            workLines.Add(new WorkLine("open collage.png in the default program"));
        }

        static void Render()
        {
            UI.Wipe();
            linePositions.Clear(); // Reset line positions

            int currentY = 0;
            int consoleWidth = Console.WindowWidth;
            int consoleHeight = Console.WindowHeight;

            for (int i = 0; i < workLines.Count; i++)
            {
                var line = workLines[i];
                linePositions.Add(currentY);

                if (i == selectedIndex)
                {
                    // Highlight selected line
                    Console.BackgroundColor = ConsoleColor.Blue;
                }
                else
                {
                    Console.BackgroundColor = ConsoleColor.Black;
                }

                Message.Send(MessageType.Raw, $"{line.GetPrefix()}{line.Instruction}");
                Console.ResetColor();
                currentY++;

                var code = line.GetActualCode();
                // If expanded, show the box
                if (line.State == LineState.Expanded && !string.IsNullOrEmpty(code))
                {
                    // Calculate box position and size
                    int boxStartX = 0;
                    int boxStartY = currentY;
                    //Width = text.Split('\n').Max(x => x.StripAnsiColorCodes().Length) + 2;
                    //Height = text.Split('\n').Length + 2;
                    int maxBoxWidth = code.Split('\n').Max(x => x.StripAnsiColorCodes().Length) + 2;
                    int maxBoxHeight = code.Trim().Split('\n').Length + 2;

                    // Display the box
                    
                    ConsoleBox.Show(line.GetActualCode(), boxStartX, boxStartY, maxBoxWidth, maxBoxHeight);
                    Console.WriteLine();
                    // Calculate how many lines the box takes
                    int wrappedLineCount = maxBoxHeight;
                    currentY += wrappedLineCount;
                }
            }

            // Instructions at the bottom
            if (currentY < consoleHeight - 1)
            {
                Console.SetCursorPosition(0, currentY);
                Message.Send("\nUse Up/Down arrows to navigate, Space to interact, Esc to exit.");
            }
        }

        // Helper method to count wrapped lines
        static int CountWrappedLines(string text, int maxLineLength)
        {
            var wrappedText = ConsoleBox.ShowTextForWrapping(text, maxLineLength);
            return wrappedText.Split('\n').Length;
        }

        static async Task HandleSpace()
        {
            var line = workLines[selectedIndex];
            switch (line.State)
            {
                case LineState.Ungenerated:
                    await GenerateLine(line);
                    break;
                case LineState.Collapsed:
                    ExpandLine(line);
                    break;
                case LineState.Expanded:
                    CollapseLine(line);
                    break;
            }
        }

        static async Task GenerateLine(WorkLine line)
        {
            // Prepare prompt
            string fullProgram = string.Join("\n", workLines.Select(l => l.Instruction));
            string prompt = $"Write a python program that represents a line in the program. Here is the full program in natural language:\n{fullProgram}\n. You will ONLY write the code for the line \n\n{line.Instruction}\n\nOnly respond with Python code in a python code block.";
            string conversationId = Guid.NewGuid().ToString();

            StringBuilder generated = new StringBuilder();

            // Start streaming
            await foreach (var token in AI.GetStream(prompt, conversationId, true))
            {
                generated.Append(token);
                lock (lockObj)
                {
                    line.State = LineState.Expanded;
                    line.GeneratedCode = generated.ToString();
                    Render();
                }
            }
        }

        static void ExpandLine(WorkLine line)
        {
            if (!string.IsNullOrEmpty(line.GeneratedCode))
            {
                line.State = LineState.Expanded;
            }
        }

        static void CollapseLine(WorkLine line)
        {
            if (!string.IsNullOrEmpty(line.GeneratedCode))
            {
                line.State = LineState.Collapsed;
            }
        }
        // Class representing a single line in Worklines
        class WorkLine
        {
            public string Instruction { get; set; }
            public LineState State { get; set; }
            public string GeneratedCode { get; set; }

            public string GetActualCode() => GeneratedCode.ExtractCode();

            // Position of the ConsoleBox if expanded
            public ConsoleBox Box { get; set; }

            public WorkLine(string instruction)
            {
                Instruction = instruction;
                State = LineState.Ungenerated;
                GeneratedCode = string.Empty;
                Box = null;
            }

            public string GetPrefix()
            {
                switch (State)
                {
                    case LineState.Ungenerated:
                        return "~ ";
                    case LineState.Collapsed:
                        return "+ ";
                    case LineState.Expanded:
                        return "- ";
                    default:
                        return "~ ";
                }
            }
        }
    }
}

Add these changes:

pressing R regenerates the code in the currently selected box
pressing N will make a new line and set the cursor to visible at that position to edit it (background color green in edit mode, Console.ReadLine it). Enter to confirm edit, escape to cancel edit
the generating text should be visible as it's being generated in the box.

write the full code with these changes