module A201802.LR0Lemmas where

open import A201801.Prelude
open import A201801.Category
open import A201801.Fin
open import A201801.FinLemmas
open import A201801.Vec
open import A201801.VecLemmas

open import A201802.LR0


--------------------------------------------------------------------------------
{-
                      GET (RENS e τ) I ≡ (REN e ∘ GET τ) I                      comp-REN-GET
                   GETS (RENS e₁ τ) e₂ ≡ (RENS e₁ ∘ GETS τ) e₂                  comp-RENS-GETS
             (GETS (LIFTS τ) ∘ keep) e ≡ (LIFTS ∘ GETS τ) e                     comp-LIFTS-GETS
                             GET IDS I ≡ VAR I                                  GET-VAR

                              REN id M ≡ M                                      id-REN
                             RENS id τ ≡ τ                                      id-RENS
                       REN (e₁ ∘ e₂) M ≡ (REN e₂ ∘ REN e₁) M                    comp-REN
                      RENS (e₁ ∘ e₂) τ ≡ (RENS e₂ ∘ RENS e₁) τ                  comp-RENS
                                                                                𝐑𝐄𝐍
                                                                                𝐑𝐄𝐍𝐒

                 (REN (keep e) ∘ WK) M ≡ (WK ∘ REN e) M                         comp-WK-REN-keep
               (RENS (keep e) ∘ WKS) τ ≡ (WKS ∘ RENS e) τ                       comp-WKS-RENS-keep
             (RENS (keep e) ∘ LIFTS) τ ≡ (LIFTS ∘ RENS e) τ                     comp-LIFTS-RENS

                      GET (SUBS τ υ) I ≡ (SUB τ ∘ GET υ) I                      comp-SUB-GET
                      SUB (GETS τ e) M ≡ (SUB τ ∘ REN e) M                      comp-SUB-REN
                  (SUB (τ , M) ∘ WK) N ≡ SUB τ N                                simp-SUB
                (SUBS (τ , M) ∘ WKS) υ ≡ SUBS τ υ                               simp-SUBS

                      SUB (RENS e τ) M ≡ (REN e ∘ SUB τ) M                      comp-REN-SUB
                     SUBS (RENS e τ) υ ≡ (RENS e ∘ SUBS τ) υ                    comp-RENS-SUBS
            (SUBS (LIFTS τ) ∘ LIFTS) υ ≡ (LIFTS ∘ SUBS τ) υ                     comp-LIFTS-SUBS

                             SUB IDS M ≡ M                                      id-SUB
                            SUBS IDS τ ≡ τ                                      lid-SUBS
                            SUBS τ IDS ≡ τ                                      rid-SUBS
                      SUB (SUBS τ υ) M ≡ (SUB τ ∘ SUB υ) M                      comp-SUB
                     SUBS (SUBS τ υ) ν ≡ (SUBS τ ∘ SUBS υ) ν                    assoc-SUBS
                                                                                𝐓𝐞𝐫𝐦𝐬
                                                                                𝐒𝐔𝐁

             (CUT M ∘ SUB (LIFTS τ)) N ≡ SUB (τ , M) N                          simp-CUT-SUB
-}
--------------------------------------------------------------------------------


comp-REN-GET :  {g g′ n}  (e : g′  g) (τ : Terms g n) (I : Fin n)
                           GET (RENS e τ) I  (REN e  GET τ) I
comp-REN-GET e (τ , M) zero    = refl
comp-REN-GET e (τ , N) (suc I) = comp-REN-GET e τ I


comp-RENS-GETS :  {g g′ n n′}  (e₁ : g′  g) (τ : Terms g n′) (e₂ : n′  n)
                                GETS (RENS e₁ τ) e₂  (RENS e₁  GETS τ) e₂
comp-RENS-GETS e₁        done      = refl
comp-RENS-GETS e₁ (τ , N) (drop e₂) = comp-RENS-GETS e₁ τ e₂
comp-RENS-GETS e₁ (τ , M) (keep e₂) = (_, REN e₁ M) & comp-RENS-GETS e₁ τ e₂


comp-LIFTS-GETS :  {g n n′}  (τ : Terms g n′) (e : n′  n)
                              (GETS (LIFTS τ)  keep) e  (LIFTS  GETS τ) e
comp-LIFTS-GETS τ e = (_, VZ) & comp-RENS-GETS (drop id) τ e


GET-VAR :  {g}  (I : Fin g)
                 GET IDS I  VAR I
GET-VAR zero    = refl
GET-VAR (suc I) = comp-REN-GET (drop id) IDS I
                 WK & GET-VAR I
                 (\ i′  VAR (suc i′)) & id-REN∋ I


--------------------------------------------------------------------------------


id-REN :  {g}  (M : Term g)
                REN id M  M
id-REN (VAR I)      = VAR & id-REN∋ I
id-REN (LAM M)      = LAM & id-REN M
id-REN (APP M N)    = APP & id-REN M  id-REN N
id-REN (PAIR M N)   = PAIR & id-REN M  id-REN N
id-REN (FST M)      = FST & id-REN M
id-REN (SND M)      = SND & id-REN M
id-REN UNIT         = refl
id-REN (ABORT M)    = ABORT & id-REN M
id-REN (LEFT M)     = LEFT & id-REN M
id-REN (RIGHT M)    = RIGHT & id-REN M
id-REN (CASE M N O) = CASE & id-REN M  id-REN N  id-REN O
id-REN TRUE         = refl
id-REN FALSE        = refl
id-REN (IF M N O)   = IF & id-REN M  id-REN N  id-REN O


id-RENS :  {g n}  (τ : Terms g n)
                   RENS id τ  τ
id-RENS        = refl
id-RENS (τ , M) = _,_ & id-RENS τ  id-REN M


comp-REN :  {g g′ g″}  (e₁ : g′  g) (e₂ : g″  g′) (M : Term g)
                        REN (e₁  e₂) M  (REN e₂  REN e₁) M
comp-REN e₁ e₂ (VAR I)      = VAR & comp-REN∋ e₁ e₂ I
comp-REN e₁ e₂ (LAM M)      = LAM & comp-REN (keep e₁) (keep e₂) M
comp-REN e₁ e₂ (APP M N)    = APP & comp-REN e₁ e₂ M  comp-REN e₁ e₂ N
comp-REN e₁ e₂ (PAIR M N)   = PAIR & comp-REN e₁ e₂ M  comp-REN e₁ e₂ N
comp-REN e₁ e₂ (FST M)      = FST & comp-REN e₁ e₂ M
comp-REN e₁ e₂ (SND M)      = SND & comp-REN e₁ e₂ M
comp-REN e₁ e₂ UNIT         = refl
comp-REN e₁ e₂ (ABORT M)    = ABORT & comp-REN e₁ e₂ M
comp-REN e₁ e₂ (LEFT M)     = LEFT & comp-REN e₁ e₂ M
comp-REN e₁ e₂ (RIGHT M)    = RIGHT & comp-REN e₁ e₂ M
comp-REN e₁ e₂ (CASE M N O) = CASE & comp-REN e₁ e₂ M
                                    comp-REN (keep e₁) (keep e₂) N
                                    comp-REN (keep e₁) (keep e₂) O
comp-REN e₁ e₂ TRUE         = refl
comp-REN e₁ e₂ FALSE        = refl
comp-REN e₁ e₂ (IF M N O)   = IF & comp-REN e₁ e₂ M
                                  comp-REN e₁ e₂ N
                                  comp-REN e₁ e₂ O


comp-RENS :  {g g′ g″ n}  (e₁ : g′  g) (e₂ : g″  g′) (τ : Terms g n)
                           RENS (e₁  e₂) τ  (RENS e₂  RENS e₁) τ
comp-RENS e₁ e₂        = refl
comp-RENS e₁ e₂ (τ , M) = _,_ & comp-RENS e₁ e₂ τ  comp-REN e₁ e₂ M


𝐑𝐄𝐍 : Presheaf 𝐆𝐄𝐐 Term
𝐑𝐄𝐍 = record
        {      = REN
        ; idℱ   = funext! id-REN
        ; compℱ = \ e₁ e₂  funext! (comp-REN e₁ e₂)
        }


𝐑𝐄𝐍𝐒 :  {n}  Presheaf 𝐆𝐄𝐐 (\ g  Terms g n)
𝐑𝐄𝐍𝐒 = record
         {      = RENS
         ; idℱ   = funext! id-RENS
         ; compℱ = \ e₁ e₂  funext! (comp-RENS e₁ e₂)
         }


--------------------------------------------------------------------------------


comp-WK-REN-keep :  {g g′}  (e : g′  g) (M : Term g)
                             (REN (keep e)  WK) M  (WK  REN e) M
comp-WK-REN-keep e M = comp-REN (drop id) (keep e) M ⁻¹
                      (\ e′  REN (drop e′) M) & (lid∘ e  rid∘ e ⁻¹)
                      comp-REN e (drop id) M


comp-WKS-RENS-keep :  {g g′ n}  (e : g′  g) (τ : Terms g n)
                                 (RENS (keep e)  WKS) τ  (WKS  RENS e) τ
comp-WKS-RENS-keep e        = refl
comp-WKS-RENS-keep e (τ , M) = _,_ & comp-WKS-RENS-keep e τ  comp-WK-REN-keep e M


comp-LIFTS-RENS :  {g g′ n}  (e : g′  g) (τ : Terms g n)
                              (RENS (keep e)  LIFTS) τ  (LIFTS  RENS e) τ
comp-LIFTS-RENS e τ = (_, VZ) & comp-WKS-RENS-keep e τ


--------------------------------------------------------------------------------


comp-SUB-GET :  {g n m}  (τ : Terms g n) (υ : Terms n m) (I : Fin m)
                          GET (SUBS τ υ) I  (SUB τ  GET υ) I
comp-SUB-GET τ (υ , M) zero    = refl
comp-SUB-GET τ (υ , N) (suc I) = comp-SUB-GET τ υ I


comp-SUB-REN :  {g n n′}  (τ : Terms g n′) (e : n′  n) (M : Term n)
                           SUB (GETS τ e) M  (SUB τ  REN e) M
comp-SUB-REN τ e (VAR I)      = comp-GET-REN∋ τ e I
comp-SUB-REN τ e (LAM M)      = LAM & ( (\ τ′  SUB τ′ M) & comp-LIFTS-GETS τ e ⁻¹
                                       comp-SUB-REN (LIFTS τ) (keep e) M
                                      )
comp-SUB-REN τ e (APP M N)    = APP & comp-SUB-REN τ e M  comp-SUB-REN τ e N
comp-SUB-REN τ e (PAIR M N)   = PAIR & comp-SUB-REN τ e M  comp-SUB-REN τ e N
comp-SUB-REN τ e (FST M)      = FST & comp-SUB-REN τ e M
comp-SUB-REN τ e (SND M)      = SND & comp-SUB-REN τ e M
comp-SUB-REN τ e UNIT         = refl
comp-SUB-REN τ e (ABORT M)    = ABORT & comp-SUB-REN τ e M
comp-SUB-REN τ e (LEFT M)     = LEFT & comp-SUB-REN τ e M
comp-SUB-REN τ e (RIGHT M)    = RIGHT & comp-SUB-REN τ e M
comp-SUB-REN τ e (CASE M N O) = CASE & comp-SUB-REN τ e M
                                      ( (\ τ′  SUB τ′ N) & comp-LIFTS-GETS τ e ⁻¹
                                        comp-SUB-REN (LIFTS τ) (keep e) N
                                       )
                                      ( (\ τ′  SUB τ′ O) & comp-LIFTS-GETS τ e ⁻¹
                                        comp-SUB-REN (LIFTS τ) (keep e) O
                                       )
comp-SUB-REN τ e TRUE         = refl
comp-SUB-REN τ e FALSE        = refl
comp-SUB-REN τ e (IF M N O)   = IF & comp-SUB-REN τ e M
                                    comp-SUB-REN τ e N
                                    comp-SUB-REN τ e O


simp-SUB :  {g n}  (τ : Terms g n) (M : Term g) (N : Term n)
                    (SUB (τ , M)  WK) N  SUB τ N
simp-SUB τ M N = comp-SUB-REN (τ , M) (drop id) N ⁻¹
                (\ τ′  SUB τ′ N) & id-GETS τ


simp-SUBS :  {g n m}  (τ : Terms g n) (M : Term g) (υ : Terms n m)
                       (SUBS (τ , M)  WKS) υ  SUBS τ υ
simp-SUBS τ M        = refl
simp-SUBS τ M (υ , N) = _,_ & simp-SUBS τ M υ  simp-SUB τ M N


--------------------------------------------------------------------------------


comp-REN-SUB :  {g g′ n}  (e : g′  g) (τ : Terms g n) (M : Term n)
                           SUB (RENS e τ) M  (REN e  SUB τ) M
comp-REN-SUB e τ (VAR I)      = comp-REN-GET e τ I
comp-REN-SUB e τ (LAM M)      = LAM & ( (\ τ′  SUB τ′ M) & comp-LIFTS-RENS e τ ⁻¹
                                       comp-REN-SUB (keep e) (LIFTS τ) M
                                      )
comp-REN-SUB e τ (APP M N)    = APP & comp-REN-SUB e τ M  comp-REN-SUB e τ N
comp-REN-SUB e τ (PAIR M N)   = PAIR & comp-REN-SUB e τ M  comp-REN-SUB e τ N
comp-REN-SUB e τ (FST M)      = FST & comp-REN-SUB e τ M
comp-REN-SUB e τ (SND M)      = SND & comp-REN-SUB e τ M
comp-REN-SUB e τ UNIT         = refl
comp-REN-SUB e τ (ABORT M)    = ABORT & comp-REN-SUB e τ M
comp-REN-SUB e τ (LEFT M)     = LEFT & comp-REN-SUB e τ M
comp-REN-SUB e τ (RIGHT M)    = RIGHT & comp-REN-SUB e τ M
comp-REN-SUB e τ (CASE M N O) = CASE & comp-REN-SUB e τ M
                                      ( (\ τ′  SUB τ′ N) & comp-LIFTS-RENS e τ ⁻¹
                                        comp-REN-SUB (keep e) (LIFTS τ) N
                                       )
                                      ( (\ τ′  SUB τ′ O) & comp-LIFTS-RENS e τ ⁻¹
                                        comp-REN-SUB (keep e) (LIFTS τ) O
                                       )
comp-REN-SUB e τ TRUE         = refl
comp-REN-SUB e τ FALSE        = refl
comp-REN-SUB e τ (IF M N O)   = IF & comp-REN-SUB e τ M
                                    comp-REN-SUB e τ N
                                    comp-REN-SUB e τ O


comp-RENS-SUBS :  {g g′ n m}  (e : g′  g) (τ : Terms g n) (υ : Terms n m)
                               SUBS (RENS e τ) υ  (RENS e  SUBS τ) υ
comp-RENS-SUBS e τ        = refl
comp-RENS-SUBS e τ (υ , M) = _,_ & comp-RENS-SUBS e τ υ  comp-REN-SUB e τ M


comp-LIFTS-SUBS :  {g n m}  (τ : Terms g n) (υ : Terms n m)
                             (SUBS (LIFTS τ)  LIFTS) υ  (LIFTS  SUBS τ) υ
comp-LIFTS-SUBS τ υ = (_, VZ) & ( simp-SUBS (WKS τ) VZ υ
                                 comp-RENS-SUBS (drop id) τ υ
                                )


--------------------------------------------------------------------------------


id-SUB :  {g}  (M : Term g)
                SUB IDS M  M
id-SUB (VAR I)      = GET-VAR I
id-SUB (LAM M)      = LAM & id-SUB M
id-SUB (APP M N)    = APP & id-SUB M  id-SUB N
id-SUB (PAIR M N)   = PAIR & id-SUB M  id-SUB N
id-SUB (FST M)      = FST & id-SUB M
id-SUB (SND M)      = SND & id-SUB M
id-SUB UNIT         = refl
id-SUB (ABORT M)    = ABORT & id-SUB M
id-SUB (LEFT M)     = LEFT & id-SUB M
id-SUB (RIGHT M)    = RIGHT & id-SUB M
id-SUB (CASE M N O) = CASE & id-SUB M  id-SUB N  id-SUB O
id-SUB TRUE         = refl
id-SUB FALSE        = refl
id-SUB (IF M N O)   = IF & id-SUB M  id-SUB N  id-SUB O


lid-SUBS :  {g n}  (τ : Terms g n)
                    SUBS IDS τ  τ
lid-SUBS        = refl
lid-SUBS (τ , M) = _,_ & lid-SUBS τ  id-SUB M


rid-SUBS :  {g n}  (τ : Terms g n)
                    SUBS τ IDS  τ
rid-SUBS        = refl
rid-SUBS (τ , M) = (_, M) & ( simp-SUBS τ M IDS
                             rid-SUBS τ
                            )


comp-SUB :  {g m n}  (τ : Terms g n) (υ : Terms n m) (M : Term m)
                      SUB (SUBS τ υ) M  (SUB τ  SUB υ) M
comp-SUB τ υ (VAR I)      = comp-SUB-GET τ υ I
comp-SUB τ υ (LAM M)      = LAM & ( (\ τ′  SUB τ′ M) & comp-LIFTS-SUBS τ υ ⁻¹
                                   comp-SUB (LIFTS τ) (LIFTS υ) M
                                  )
comp-SUB τ υ (APP M N)    = APP & comp-SUB τ υ M  comp-SUB τ υ N
comp-SUB τ υ (PAIR M N)   = PAIR & comp-SUB τ υ M  comp-SUB τ υ N
comp-SUB τ υ (FST M)      = FST & comp-SUB τ υ M
comp-SUB τ υ (SND M)      = SND & comp-SUB τ υ M
comp-SUB τ υ UNIT         = refl
comp-SUB τ υ (ABORT M)    = ABORT & comp-SUB τ υ M
comp-SUB τ υ (LEFT M)     = LEFT & comp-SUB τ υ M
comp-SUB τ υ (RIGHT M)    = RIGHT & comp-SUB τ υ M
comp-SUB τ υ (CASE M N O) = CASE & comp-SUB τ υ M
                                  ( (\ τ′  SUB τ′ N) & comp-LIFTS-SUBS τ υ ⁻¹
                                    comp-SUB (LIFTS τ) (LIFTS υ) N
                                   )
                                  ( (\ τ′  SUB τ′ O) & comp-LIFTS-SUBS τ υ ⁻¹
                                    comp-SUB (LIFTS τ) (LIFTS υ) O
                                   )
comp-SUB τ υ TRUE         = refl
comp-SUB τ υ FALSE        = refl
comp-SUB τ υ (IF M N O)   = IF & comp-SUB τ υ M
                                comp-SUB τ υ N
                                comp-SUB τ υ O


assoc-SUBS :  {g n m l}  (τ : Terms g n) (υ : Terms n m) (ν : Terms m l)
                          SUBS (SUBS τ υ) ν  (SUBS τ  SUBS υ) ν
assoc-SUBS τ υ        = refl
assoc-SUBS τ υ (ν , M) = _,_ & assoc-SUBS τ υ ν  comp-SUB τ υ M


instance
  𝐓𝐞𝐫𝐦𝐬 : Category Nat Terms
  𝐓𝐞𝐫𝐦𝐬 = record
            { id     = IDS
            ; _∘_    = flip SUBS
            ; lid∘   = rid-SUBS
            ; rid∘   = lid-SUBS
            ; assoc∘ = \ ν υ τ  assoc-SUBS τ υ ν ⁻¹
            }


𝐒𝐔𝐁 : Presheaf 𝐓𝐞𝐫𝐦𝐬 Term
𝐒𝐔𝐁 = record
        {      = SUB
        ; idℱ   = funext! id-SUB
        ; compℱ = \ υ τ  funext! (comp-SUB τ υ)
        }


--------------------------------------------------------------------------------


simp-CUT-SUB :  {g n}  (M : Term g) (τ : Terms g n) (N : Term (suc n))
                        (CUT M  SUB (LIFTS τ)) N  SUB (τ , M) N
simp-CUT-SUB M τ N = comp-SUB (IDS , M) (LIFTS τ) N ⁻¹
                    (\ τ′  SUB (τ′ , M) N) & ( simp-SUBS IDS M τ
                                                 lid-SUBS τ
                                                )


--------------------------------------------------------------------------------