{-# OPTIONS --without-K --rewriting #-}

open import lib.Basics
open import lib.types.Pointed

-- sequences to facilitate equational reasoning about pointed functions

module lib.types.Pointed-seq where

module _ {i : ULevel} where

  infixr 80 _⊙◃∙_
  data ⊙→-Seq : Ptd i  Ptd i  Type (lsucc i) where
    [] : {A : Ptd i}  ⊙→-Seq A A
    _⊙◃∙_ : {A B C : Ptd i} (m : B ⊙→ C) (s : ⊙→-Seq A B)  ⊙→-Seq A C

  infix 30 _⊙→-s_
  _⊙→-s_ = ⊙→-Seq

  infix 90 _⊙◃∎
  _⊙◃∎ : {A A' : Ptd i}  A ⊙→ A'  A ⊙→-s A'
  _⊙◃∎ m = m ⊙◃∙ []

  ⊙↯ : {A A' : Ptd i} (s : A ⊙→-s A')  A ⊙→ A'
  ⊙↯ [] = ⊙idf _
  ⊙↯ (m ⊙◃∙ []) = m
  ⊙↯ {A = A} {A'} (m ⊙◃∙ s@(_ ⊙◃∙ _)) = m ⊙∘ ⊙↯ s

  record _⊙=ₛ_ {A A' : Ptd i} (s t : A ⊙→-s A') : Type i where
    constructor ⊙=ₛ-in
    field
      ⊙=ₛ-out : ⊙↯ s == ⊙↯ t
  open _⊙=ₛ_ public
  
  infix 15 _⊙∎ₛ
  _⊙∎ₛ : {A A' : Ptd i} (s : A ⊙→-s A')  s ⊙=ₛ s
  _⊙∎ₛ _ = ⊙=ₛ-in idp 

  infixr 80 _⊙-∙∙_
  _⊙-∙∙_ :  {A B C : Ptd i}  A ⊙→-s B  B ⊙→-s C  A ⊙→-s C
  _⊙-∙∙_ t [] = t
  _⊙-∙∙_ t (p ⊙◃∙ s) = p ⊙◃∙ (t ⊙-∙∙ s)

  ⊙↯-∙∙ : {A B C : Ptd i} (s : A ⊙→-s B) (t : B ⊙→-s C)
     ⊙↯ (s ⊙-∙∙ t) == ⊙↯ t ⊙∘ ⊙↯ s
  ⊙↯-∙∙ s [] = ⊙-crd∼-to-== (⊙∘-lunit _)
  ⊙↯-∙∙ [] (m ⊙◃∙ []) = idp
  ⊙↯-∙∙ (p ⊙◃∙ v) (m ⊙◃∙ []) = idp
  ⊙↯-∙∙ s (m ⊙◃∙ v@(_ ⊙◃∙ _)) = ap  p  m ⊙∘ p) (⊙↯-∙∙ s v)  ! (⊙λ= (⊙∘-assoc m _ (⊙↯ s)))

  ⊙point-from-end : {A B : Ptd i} (n : ) (s : A ⊙→-s B)  Ptd i
  ⊙point-from-end {B = B} O s = B
  ⊙point-from-end {B = B} (S n) [] = B
  ⊙point-from-end (S n) (p ⊙◃∙ s) = ⊙point-from-end n s

  ⊙take : {A B : Ptd i} (n : ) (s : A ⊙→-s B)  ⊙point-from-end n s ⊙→-s B
  ⊙take 0 s = []
  ⊙take (S n) [] = []
  ⊙take (S n) (p ⊙◃∙ s) = p ⊙◃∙ ⊙take n s 

  ⊙drop : {A B : Ptd i} (n : ) (s : A ⊙→-s B)  A ⊙→-s ⊙point-from-end n s
  ⊙drop O s = s
  ⊙drop (S n) [] = []
  ⊙drop (S n) (p ⊙◃∙ s) = ⊙drop n s

  private
    ⊙drop-take-split' : {A B : Ptd i} (n : ) (s : A ⊙→-s B)
       s == ⊙drop n s ⊙-∙∙ ⊙take n s
    ⊙drop-take-split' O s = idp
    ⊙drop-take-split' (S n) [] = idp
    ⊙drop-take-split' (S n) (p ⊙◃∙ s) = ap  v  p ⊙◃∙ v) (⊙drop-take-split' n s)

  ⊙drop-take-split : {A B : Ptd i} (n : ) (s : A ⊙→-s B)
     ⊙↯ s == ⊙↯ (⊙take n s) ⊙∘ ⊙↯ (⊙drop n s)
  ⊙drop-take-split n s =
    ⊙↯ s
      =⟨ ap ⊙↯ (⊙drop-take-split' n s) 
    ⊙↯ (⊙drop n s ⊙-∙∙ ⊙take n s)
      =⟨ ⊙↯-∙∙ (⊙drop n s) (⊙take n s) 
    ⊙↯ (⊙take n s) ⊙∘ ⊙↯ (⊙drop n s) =∎

  infix 30 _=⊙↯=_
  _=⊙↯=_ : {A B : Ptd i}  A ⊙→-s B  A ⊙→-s B  Type i
  _=⊙↯=_ s t = (⊙↯ s) == (⊙↯ t)

  module _ {A B : Ptd i} where

    infixr 80 _⊙∙ₛ_
    _⊙∙ₛ_ : {s t u : A ⊙→-s B}  s ⊙=ₛ t  t ⊙=ₛ u  s ⊙=ₛ u
    _⊙∙ₛ_ (⊙=ₛ-in p) (⊙=ₛ-in q) = ⊙=ₛ-in (p  q)

    abstract
      private
        infixr 10 _=⊙↯=⟨_&_&_&_⟩_
        _=⊙↯=⟨_&_&_&_⟩_ : {q : A ⊙→ B}
           (s : A ⊙→-s B)
           (n : ) (m : )
           (t : ⊙point-from-end m (⊙drop n s) ⊙→-s ⊙point-from-end n s)
           ⊙take m (⊙drop n s) =⊙↯= t
           ⊙↯ ((⊙drop m (⊙drop n s) ⊙-∙∙ t) ⊙-∙∙ ⊙take n s) == q
           ⊙↯ s == q
        _=⊙↯=⟨_&_&_&_⟩_ {q} s n m t p p' =
          ⊙↯ s
            =⟨ ⊙drop-take-split n s 
          ⊙↯ (⊙take n s) ⊙∘ ⊙↯ (⊙drop n s)
            =⟨ ap (⊙↯ (⊙take n s) ⊙∘_) (⊙drop-take-split m (⊙drop n s)) 
          ⊙↯ (⊙take n s) ⊙∘ ⊙↯ (⊙take m (⊙drop n s)) ⊙∘ ⊙↯ (⊙drop m (⊙drop n s))
            =⟨ ap  v  ⊙↯ (⊙take n s) ⊙∘ v ⊙∘ ⊙↯ (⊙drop m (⊙drop n s))) p 
          ⊙↯ (⊙take n s) ⊙∘ ⊙↯ t ⊙∘ ⊙↯ (⊙drop m (⊙drop n s))
            =⟨ ap  v  ⊙↯ (⊙take n s) ⊙∘ v) (! (⊙↯-∙∙ (⊙drop m (⊙drop n s)) t)) 
          ⊙↯ (⊙take n s) ⊙∘ ⊙↯ (⊙drop m (⊙drop n s) ⊙-∙∙ t)
            =⟨ ! (⊙↯-∙∙ (⊙drop m (⊙drop n s) ⊙-∙∙ t) (⊙take n s)) 
          ⊙↯ ((⊙drop m (⊙drop n s) ⊙-∙∙ t) ⊙-∙∙ ⊙take n s)
            =⟨ p' 
          q =∎

      infixr 10 _⊙=ₛ⟨_&_&_⟩_
      _⊙=ₛ⟨_&_&_⟩_ : (s : A ⊙→-s B) {u : A ⊙→-s B}
         (n m : )
         {r : ⊙point-from-end m (⊙drop n s) ⊙→-s ⊙point-from-end n s}
         ⊙take m (⊙drop n s) ⊙=ₛ r
         ((⊙drop m (⊙drop n s) ⊙-∙∙ r) ⊙-∙∙ ⊙take n s) ⊙=ₛ u
         s ⊙=ₛ u
      _⊙=ₛ⟨_&_&_⟩_ s m n {r} p p' = ⊙=ₛ-in (s =⊙↯=⟨ m & n & r & ⊙=ₛ-out p  ⊙=ₛ-out p')

      infixr 10 _⊙=ₑ⟨_&_&_%_⟩_
      _⊙=ₑ⟨_&_&_%_⟩_ : (s : A ⊙→-s B) {u : A ⊙→-s B}
         (n m : )
         (r : ⊙point-from-end m (⊙drop n s) ⊙→-s ⊙point-from-end n s)
         ⊙take m (⊙drop n s) ⊙=ₛ r
         ((⊙drop m (⊙drop n s) ⊙-∙∙ r) ⊙-∙∙ ⊙take n s) ⊙=ₛ u
         s ⊙=ₛ u
      _⊙=ₑ⟨_&_&_%_⟩_ s m n r p p' = ⊙=ₛ-in (s =⊙↯=⟨ m & n & r & ⊙=ₛ-out p  ⊙=ₛ-out p')

      infixr 10 _⊙=ₛ⟨_⟩_
      _⊙=ₛ⟨_⟩_ : (s : A ⊙→-s B) {t u : A ⊙→-s B}
         s ⊙=ₛ t
         t ⊙=ₛ u
         s ⊙=ₛ u
      _⊙=ₛ⟨_⟩_ _ p q = p ⊙∙ₛ q

      infixr 10 _⊙=ₛ₁⟨_⟩_
      _⊙=ₛ₁⟨_⟩_ : (s : A ⊙→-s B) {u : A ⊙→-s B}
         {r : A ⊙→ B}
         ⊙↯ s == r
         r ⊙◃∎ ⊙=ₛ u
         s ⊙=ₛ u
      _⊙=ₛ₁⟨_⟩_ s {r} p p' = ⊙=ₛ-in p ⊙∙ₛ p'

      infixr 10 _⊙=ₛ₁⟨_&_&_⟩_
      _⊙=ₛ₁⟨_&_&_⟩_ : (s : A ⊙→-s B) {u : A ⊙→-s B}
         (n m : )
         {r : ⊙point-from-end m (⊙drop n s) ⊙→ ⊙point-from-end n s}
         ⊙↯ (⊙take m (⊙drop n s)) == r
         (r ⊙◃∙ ⊙drop m (⊙drop n s)) ⊙-∙∙ ⊙take n s ⊙=ₛ u
         s ⊙=ₛ u
      _⊙=ₛ₁⟨_&_&_⟩_ s m n {r} p p' = s ⊙=ₛ⟨ m & n & ⊙=ₛ-in {t = r ⊙◃∎} p  p'