import Common.Nat

namespace Substring

theorem nextn_ge (s : Substring) (n : Nat) (p : String.Pos.Raw) : s.nextn n p ≥ p := by
  unfold Substring.nextn
  cases n
  case zero => simp
  case succ nn =>
    simp
    unfold Substring.next
    simp
    if h₁ : p.offsetBy s.startPos = s.stopPos then
      simp[h₁]
      exact nextn_ge s nn p
    else
      simp[h₁]
      have h₂ : { byteIdx := (String.Pos.Raw.next s.str (p.offsetBy s.startPos)).byteIdx - s.startPos.byteIdx  : String.Pos.Raw} ≤ s.nextn nn { byteIdx := (String.Pos.Raw.next s.str (p.offsetBy s.startPos)).byteIdx - s.startPos.byteIdx } :=
        nextn_ge _ nn _
      simp[String.Pos.Raw.le_iff]
      apply Nat.le_trans  _ h₂
      unfold String.Pos.Raw.next
      simp[Char.utf8Size]
      split <;> try split <;> try split
      all_goals
      omega

theorem drop_bsize_dec (s : Substring) (n : Nat) (h₁ : ¬s.isEmpty) (h₂ : n ≠ 0) : (s.drop n).bsize < s.bsize := by
  cases n ; contradiction
  case succ nn =>
    simp only [Substring.drop, Substring.bsize, Substring.nextn, Substring.next, String.Pos.Raw.byteIdx_offsetBy, Nat.sub_eq]
    simp only [Substring.isEmpty, Substring.bsize, Nat.sub_eq, beq_iff_eq] at h₁
    if h₃ : (s.startPos.byteIdx + ({ str := s.str, startPos := s.startPos, stopPos := s.stopPos : Substring}.nextn nn (if String.Pos.Raw.offsetBy 0 s.startPos = s.stopPos then 0 else {byteIdx := (String.Pos.Raw.next s.str (String.Pos.Raw.offsetBy 0 s.startPos)).byteIdx - s.startPos.byteIdx })).byteIdx) ≤ s.stopPos.byteIdx then
      apply Nat.sub_lt_of_gt; exact h₃
      split
      case h₂.isTrue hx =>
        simp[←hx] at h₁
      case h₂.isFalse h₄ =>
        unfold String.Pos.Raw.next
        simp
        unfold Char.utf8Size
        simp
        apply Nat.lt_of_lt_of_le _ (nextn_ge { str := s.str, startPos := s.startPos, stopPos := s.stopPos } nn _)
        split <;> try split <;> try split
        all_goals
          simp
    else
      have h₄ : s.stopPos.byteIdx - (s.startPos.byteIdx + ({ str := s.str, startPos := s.startPos, stopPos := s.stopPos : Substring }.nextn nn (if String.Pos.Raw.offsetBy 0 s.startPos = s.stopPos then 0 else {byteIdx := (String.Pos.Raw.next s.str (String.Pos.Raw.offsetBy 0 s.startPos)).byteIdx - s.startPos.byteIdx })).byteIdx) = 0 := by
        omega
      rw[h₄]
      omega
