//
// Copyright (c) 2024, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   08 Oct 2024  Matthew Giannini  Creation
//

**
** A line or portion of a line from the markdown source text
**
@Js
const class SourceLine
{

//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////

  new make(Str content, SourceSpan? sourceSpan := null)
  {
    this.content = content
    this.sourceSpan = sourceSpan
  }

  ** The line content
  const Str content

  ** The source span if the parser was configured to include it
  const SourceSpan? sourceSpan

  ** Get a new source line that is a substring of this one.
  ** The beginIndex is inclusive, and the endIndex is exclusive.
  SourceLine substring(Int beginIndex, Int endIndex)
  {
    if (beginIndex < 0) throw ArgErr("beginIndex: ${beginIndex}")
    if (endIndex < 0) throw ArgErr("endIndex: ${endIndex}")
    newContent := this.content[beginIndex..<endIndex]
    SourceSpan? newSourceSpan := null
    if (sourceSpan != null)
    {
      colIndex := sourceSpan.columnIndex + beginIndex
      len := endIndex - beginIndex
      if (len != 0)
        newSourceSpan = SourceSpan(sourceSpan.lineIndex, colIndex, len)
    }
    return SourceLine(newContent, newSourceSpan)
  }

  override Str toStr() { "sourceLine(content=${content})" }
}

**************************************************************************
** SourceLines
**************************************************************************

**
** A set of lines (`SourceLine`) from the input source.
**
@Js
class SourceLines
{
  static new empty() { SourceLines([,]) }

  new makeOne(SourceLine line) : this.make([line]) { }

  new make(SourceLine[] lines)
  {
    this.lines.addAll(lines)
  }

  SourceLine[] lines := [,] { private set }

  Bool isEmpty() { lines.isEmpty }

  Void addLine(SourceLine line) { lines.add(line) }

  Str content()
  {
    sb := StrBuf()
    lines.each |line, i|
    {
      if (i != 0) sb.addChar('\n')
      sb.add(line.content)
    }
    return sb.toStr
  }

  SourceSpan[] sourceSpans()
  {
    sourceSpans := SourceSpan[,]
    lines.each |line|
    {
      sourceSpan := line.sourceSpan
      if (sourceSpan != null) sourceSpans.add(sourceSpan)
    }
    return sourceSpans
  }
}