text editor inspired vim and yi
import ViE.State
import ViE.Types
import ViE.Buffer.Content
import ViE.Buffer.LowIO
import ViE.Workspace

namespace ViE.Buffer

open ViE

def createNewBuffer (state : EditorState) (content : TextBuffer) (filename : Option String) : (Nat × EditorState) :=
  let s' := state.updateCurrentWorkspace fun ws =>
    let id := ws.nextBufferId
    let buildLeafBits := state.config.searchBloomBuildLeafBits
    let buf : FileBuffer := ViE.Buffer.fileBufferFromTextBufferWithConfig id filename content buildLeafBits
    { ws with buffers := buf :: ws.buffers, nextBufferId := id + 1 }
  let ws := s'.getCurrentWorkspace
  (ws.nextBufferId - 1, s')

def addBuffer (state : EditorState) (buf : FileBuffer) : (Nat × EditorState) :=
  let s' := state.updateCurrentWorkspace fun ws =>
    let id := ws.nextBufferId
    let newBuf := { buf with id := id }
    { ws with buffers := newBuf :: ws.buffers, nextBufferId := id + 1 }
  let ws := s'.getCurrentWorkspace
  (ws.nextBufferId - 1, s')

def removeBuffer (state : EditorState) (bufId : Nat) : EditorState :=
  state.updateCurrentWorkspace fun ws =>
    { ws with buffers := ws.buffers.filter (fun b => b.id != bufId) }

def findBufferByFilename (state : EditorState) (fname : String) : Option Nat :=
  let ws := state.getCurrentWorkspace
  ws.buffers.find? (fun b => b.filename == some fname) |>.map (fun b => b.id)

/-- Open a file buffer in the active window. Loads from disk if necessary. -/
def openBuffer (state : EditorState) (filename : String) : IO EditorState := do
  let resolvedPath := state.getCurrentWorkspace.resolvePath filename
  match findBufferByFilename state resolvedPath with
  | some bid =>
    -- Switch to existing buffer
    let s' := state.updateActiveView fun v => { v with bufferId := bid, cursor := {row:=0, col:=0}, scrollRow:=0, scrollCol:=0 }
    return { s' with message := s!"Switched to \"{filename}\"" }
  | none =>
    try
      let loadedBuf ← ViE.loadBufferByteArrayWithConfig resolvedPath state.config
      -- Assign new ID and add to workgroup
      let s' := state.updateCurrentWorkspace fun ws =>
        let id := ws.nextBufferId
        let buf := { loadedBuf with
          id := id
          table := { loadedBuf.table with undoLimit := state.config.historyLimit }
        }
        { ws with buffers := buf :: ws.buffers, nextBufferId := id + 1 }

      let ws := s'.getCurrentWorkspace
      let bid := ws.nextBufferId - 1

      let s'' := s'.updateActiveView fun v => { v with bufferId := bid, cursor := {row:=0, col:=0}, scrollRow:=0, scrollCol:=0 }
      return { s'' with message := s!"Loaded \"{filename}\"" }
    catch e =>
      return { state with message := s!"Error loading file: {e}" }


end ViE.Buffer