{-# OPTIONS --safe --without-K --postfix-projections #-}

module STT.Contextual where

open import Function using (_∋_; _↔_; mk↔ₛ′)
open import Relation.Binary.PropositionalEquality
  using (_≡_; refl; sym; cong; module ≡-Reasoning)
open ≡-Reasoning

module _ (Ty : Set) where
  infixl 2 _▹_
  data Con-of : Set where
     : Con-of
    _▹_ : Con-of  Ty  Con-of

record CwF : Set₁ where
  no-eta-equality

  field Ty : Set
  Con : Set
  Con = Con-of Ty

  infixl 9 _∘_ _[_]
  infixl 4 _,_
  infixr 0 _⇒_
  field
    Sub : Con  Con  Set

    _∘_ :  {Θ Δ Γ}  Sub Δ Γ  Sub Θ Δ  Sub Θ Γ
    assoc :
       {Ξ Θ Δ Γ} (γ : Sub Δ Γ) (δ : Sub Θ Δ) (θ : Sub Ξ Θ) 
      γ  (δ  θ)  γ  δ  θ

    id :  {Γ}  Sub Γ Γ
    idr :  {Δ Γ} (γ : Sub Δ Γ)  γ  id  γ
    idl :  {Δ Γ} (γ : Sub Δ Γ)  id  γ  γ

    Tm : Con  Ty  Set
    _[_] :  {Δ Γ A}  Tm Γ A  Sub Δ Γ  Tm Δ A
    []-∘ :
       {Θ Δ Γ A} (a : Tm Γ A) (γ : Sub Δ Γ) (δ : Sub Θ Δ) 
      a [ γ  δ ]  a [ γ ] [ δ ]
    []-id :  {Γ A} (a : Tm Γ A)  a [ id ]  a

    ε :  {Γ}  Sub Γ 
    ε-∘ :  {Δ Γ} (γ : Sub Δ Γ)  ε  γ  ε
    ◆-η : ε  id

    p :  {Γ A}  Sub (Γ  A) Γ
    q :  {Γ A}  Tm (Γ  A) A

    _,_ :  {Δ Γ A}  Sub Δ Γ  Tm Δ A  Sub Δ (Γ  A)
    ,-∘ :
       {Θ Δ Γ A} (γ : Sub Δ Γ) (a : Tm Δ A) (δ : Sub Θ Δ) 
      (γ , a)  δ  (γ  δ , a [ δ ])

    ▹-β₁ :  {Δ Γ A} (γ : Sub Δ Γ) (a : Tm Δ A)  p  (γ , a)  γ
    ▹-β₂ :  {Δ Γ A} (γ : Sub Δ Γ) (a : Tm Δ A)  q [ γ , a ]  a
    ▹-η :  {Γ A}  (p , q)  id {Γ  A}

    ι : Ty
    _⇒_ : Ty  Ty  Ty

    app :  {Γ A B}  Tm Γ (A  B)  Tm Γ A  Tm Γ B
    app-[] :
       {Δ Γ A B} (f : Tm Γ (A  B)) a (γ : Sub Δ Γ) 
      app f a [ γ ]  app (f [ γ ]) (a [ γ ])

    lam :  {Γ A B}  Tm (Γ  A) B  Tm Γ (A  B)
    lam-[] :
       {Δ Γ A B} (b : Tm (Γ  A) B) (γ : Sub Δ Γ) 
      lam b [ γ ]  lam (b [ γ  p , q ])

    ⇒-β :  {Γ A B} (b : Tm (Γ  A) B) a  app (lam b) a  b [ id , a ]
    ⇒-η :  {Γ A B} (f : Tm Γ (A  B))  lam (app (f [ p ]) q)  f

module _ (Ty : Set) (Tm : Con-of Ty  Ty  Set) where
  infixl 10 _⁺
  data SSub-of : Con-of Ty  Con-of Ty  Set where
    pₛ :  {Γ A}  SSub-of (Γ  A) Γ
    _⁺ :  {Δ Γ A}  SSub-of Δ Γ  SSub-of (Δ  A) (Γ  A)
    ⟨_⟩ :  {Γ A}  Tm Γ A  SSub-of Γ (Γ  A)

record SSC : Set₁ where
  no-eta-equality

  field Ty : Set
  Con : Set
  Con = Con-of Ty

  field Tm : Con  Ty  Set
  SSub : Con  Con  Set
  SSub = SSub-of Ty Tm

  p :  {Γ A}  SSub (Γ  A) Γ
  p = pₛ

  infixl 9 _[_]
  infixr 0 _⇒_
  field
    _[_] :  {Δ Γ A}  Tm Γ A  SSub Δ Γ  Tm Δ A
    q :  {Γ A}  Tm (Γ  A) A

    p-⁺ :
       {Δ Γ A B} (b : Tm Γ B) (γ : SSub Δ Γ) 
      (Tm (Δ  A) B  b [ p ] [ γ  ])  b [ γ ] [ p ]
    q-⁺ :  {Δ Γ A} (γ : SSub Δ Γ)  (Tm (Δ  A) A  q [ γ  ])  q

    ⟨⟩-[] :
       {Δ Γ A B} (b : Tm (Γ  A) B) (a : Tm Γ A) (γ : SSub Δ Γ) 
      b [  a  ] [ γ ]  b [ γ  ] [  a [ γ ]  ]
    p-⟨⟩ :  {Γ A B} (b : Tm Γ B) (a : Tm Γ A)  b [ p ] [  a  ]  b
    q-⟨⟩ :  {Γ A} (a : Tm Γ A)  q [  a  ]  a
    ▹-η :  {Γ A B} (b : Tm (Γ  A) B)  b [ p  ] [  q  ]  b

    ι : Ty
    _⇒_ : Ty  Ty  Ty

    app :  {Γ A B}  Tm Γ (A  B)  Tm Γ A  Tm Γ B
    app-[] :
       {Δ Γ A B} (f : Tm Γ (A  B)) a (γ : SSub Δ Γ) 
      app f a [ γ ]  app (f [ γ ]) (a [ γ ])

    lam :  {Γ A B}  Tm (Γ  A) B  Tm Γ (A  B)
    lam-[] :
       {Δ Γ A B} (b : Tm (Γ  A) B) (γ : SSub Δ Γ) 
      lam b [ γ ]  lam (b [ γ  ])

    ⇒-β :  {Γ A B} (b : Tm (Γ  A) B) a  app (lam b) a  b [  a  ]
    ⇒-η :  {Γ A B} (f : Tm Γ (A  B))  lam (app (f [ p ]) q)  f

module CwF→SSC (M : CwF) where
  open CwF M

  SSub : Con  Con  Set
  SSub = SSub-of Ty Tm

  SS→S :  {Δ Γ}  SSub Δ Γ  Sub Δ Γ
  SS→S pₛ = p
  SS→S (γ ) = SS→S γ  p , q
  SS→S  a  = id , a

module _ (M : CwF) where
  open CwF M
  open CwF→SSC M

  CwF→SSC : SSC
  CwF→SSC .SSC.Ty = Ty
  CwF→SSC .SSC.Tm = Tm

  CwF→SSC .SSC._[_] a γ = a [ SS→S γ ]
  CwF→SSC .SSC.q = q

  CwF→SSC .SSC.p-⁺ b γ = begin
    b [ p ] [ SS→S γ  p , q ] ≡˘⟨ []-∘ _ _ _ 
    b [ p  (SS→S γ  p , q) ] ≡⟨ cong  x  b [ x ]) (▹-β₁ _ _) 
    b [ SS→S γ  p ]           ≡⟨ []-∘ _ _ _ 
    b [ SS→S γ ] [ p ]         
  CwF→SSC .SSC.q-⁺ γ = ▹-β₂ _ _

  CwF→SSC .SSC.⟨⟩-[] b a γ = begin
    b [ id , a ] [ SS→S γ ]                                          ≡˘⟨ []-∘ _ _ _ 
    b [ (id , a)  SS→S γ ]                                          ≡⟨ cong  x  b [ x ]) (,-∘ _ _ _) 
    b [ id  SS→S γ , a [ SS→S γ ] ]                                 ≡⟨ cong  x  b [ x , a [ SS→S γ ] ]) (idl _) 
    b [ SS→S γ , a [ SS→S γ ] ]                                      ≡˘⟨ cong  x  b [ x , a [ SS→S γ ] ]) (idr _) 
    b [ SS→S γ  id , a [ SS→S γ ] ]                                 ≡˘⟨ cong  x  b [ SS→S γ  x , a [ SS→S γ ] ]) (▹-β₁ _ _) 
    b [ SS→S γ  (p  (id , a [ SS→S γ ])) , a [ SS→S γ ] ]          ≡⟨ cong  x  b [ x , a [ SS→S γ ] ]) (assoc _ _ _) 
    b [ SS→S γ  p  (id , a [ SS→S γ ]) , a [ SS→S γ ] ]            ≡˘⟨ cong  x  b [ SS→S γ  p  (id , a [ SS→S γ ]) , x ]) (▹-β₂ _ _) 
    b [ SS→S γ  p  (id , a [ SS→S γ ]) , q [ id , a [ SS→S γ ] ] ] ≡˘⟨ cong  x  b [ x ]) (,-∘ _ _ _) 
    b [ (SS→S γ  p , q)  (id , a [ SS→S γ ]) ]                     ≡⟨ []-∘ _ _ _ 
    b [ SS→S γ  p , q ] [ id , a [ SS→S γ ] ]                       
  CwF→SSC .SSC.p-⟨⟩ b a = begin
    b [ p ] [ id , a ] ≡˘⟨ []-∘ _ _ _ 
    b [ p  (id , a) ] ≡⟨ cong  x  b [ x ]) (▹-β₁ _ _) 
    b [ id ]           ≡⟨ []-id _ 
    b                  
  CwF→SSC .SSC.q-⟨⟩ a = ▹-β₂ _ _
  CwF→SSC .SSC.▹-η b = begin
    b [ p  p , q ] [ id , q ]              ≡˘⟨ []-∘ _ _ _ 
    b [ (p  p , q)  (id , q) ]            ≡⟨ cong  x  b [ x ]) (,-∘ _ _ _) 
    b [ p  p  (id , q) , q [ id , q ] ]   ≡˘⟨ cong  x  b [ x , q [ id , q ] ]) (assoc _ _ _) 
    b [ p  (p  (id , q)) , q [ id , q ] ] ≡⟨ cong  x  b [ p  x , q [ id , q ] ]) (▹-β₁ _ _) 
    b [ p  id , q [ id , q ] ]             ≡⟨ cong  x  b [ x , q [ id , q ] ]) (idr _) 
    b [ p , q [ id , q ] ]                  ≡⟨ cong  x  b [ p , x ]) (▹-β₂ _ _) 
    b [ p , q ]                             ≡⟨ cong  x  b [ x ]) ▹-η 
    b [ id ]                                ≡⟨ []-id _ 
    b                                       

  CwF→SSC .SSC.ι = ι
  CwF→SSC .SSC._⇒_ = _⇒_

  CwF→SSC .SSC.app = app
  CwF→SSC .SSC.app-[] f a γ = app-[] _ _ _

  CwF→SSC .SSC.lam = lam
  CwF→SSC .SSC.lam-[] b γ = lam-[] _ _

  CwF→SSC .SSC.⇒-β = ⇒-β
  CwF→SSC .SSC.⇒-η = ⇒-η

module SSC→CwF (M : SSC) where
  open SSC M

  private variable
    Γ Δ Θ Ξ : Con
    A B : Ty

  infixl 9 _∘ₛ_
  data SSubs : Con  Con  Set where
    ⌜_⌝ : SSub Δ Γ  SSubs Δ Γ
    _∘ₛ_ : SSubs Δ Γ  SSubs Θ Δ  SSubs Θ Γ
    idₛ : SSubs Γ Γ

  infixl 9 _[_]ₛ
  _[_]ₛ : Tm Γ A  SSubs Δ Γ  Tm Δ A
  a [  γ  ]ₛ = a [ γ ]
  a [ γ ∘ₛ δ ]ₛ = a [ γ ]ₛ [ δ ]ₛ
  a [ idₛ ]ₛ = a

  infixl 10 _⁺ₛ
  _⁺ₛ : SSubs Δ Γ  SSubs (Δ  A) (Γ  A)
   γ  ⁺ₛ =  γ  
  (γ ∘ₛ δ) ⁺ₛ = γ ⁺ₛ ∘ₛ δ ⁺ₛ
  idₛ ⁺ₛ = idₛ

  p-⁺ₛ :
    (b : Tm Γ B) (γ : SSubs Δ Γ) 
    (Tm (Δ  A) B  b [ p ] [ γ ⁺ₛ ]ₛ)  b [ γ ]ₛ [ p ]
  p-⁺ₛ b  γ  = p-⁺ _ _
  p-⁺ₛ b (γ ∘ₛ δ) = begin
    b [ p ] [ γ ⁺ₛ ]ₛ [ δ ⁺ₛ ]ₛ ≡⟨ cong  x  x [ δ ⁺ₛ ]ₛ) (p-⁺ₛ _ γ) 
    b [ γ ]ₛ [ p ] [ δ ⁺ₛ ]ₛ    ≡⟨ p-⁺ₛ _ δ 
    b [ γ ]ₛ [ δ ]ₛ [ p ]       
  p-⁺ₛ b idₛ = refl

  q-⁺ₛ : (γ : SSubs Δ Γ)  (Tm (Δ  A) A  q [ γ ⁺ₛ ]ₛ)  q
  q-⁺ₛ  γ  = q-⁺ _
  q-⁺ₛ (γ ∘ₛ δ) = begin
    q [ γ ⁺ₛ ]ₛ [ δ ⁺ₛ ]ₛ ≡⟨ cong  x  x [ δ ⁺ₛ ]ₛ) (q-⁺ₛ γ) 
    q [ δ ⁺ₛ ]ₛ           ≡⟨ q-⁺ₛ δ 
    q                     
  q-⁺ₛ idₛ = refl

  ⟨⟩-[]ₛ :
    (b : Tm (Γ  A) B) (a : Tm Γ A) (γ : SSubs Δ Γ) 
    b [  a  ] [ γ ]ₛ  b [ γ ⁺ₛ ]ₛ [  a [ γ ]ₛ  ]
  ⟨⟩-[]ₛ b a  γ  = ⟨⟩-[] _ _ _
  ⟨⟩-[]ₛ b a (γ ∘ₛ δ) = begin
    b [  a  ] [ γ ]ₛ [ δ ]ₛ                     ≡⟨ cong  x  x [ δ ]ₛ) (⟨⟩-[]ₛ _ _ γ) 
    b [ γ ⁺ₛ ]ₛ [  a [ γ ]ₛ  ] [ δ ]ₛ           ≡⟨ ⟨⟩-[]ₛ _ _ δ 
    b [ γ ⁺ₛ ]ₛ [ δ ⁺ₛ ]ₛ [  a [ γ ]ₛ [ δ ]ₛ  ] 
  ⟨⟩-[]ₛ b a idₛ = refl

  app-[]ₛ :
     (f : Tm Γ (A  B)) a (γ : SSubs Δ Γ) 
    app f a [ γ ]ₛ  app (f [ γ ]ₛ) (a [ γ ]ₛ)
  app-[]ₛ f a  γ  = app-[] _ _ _
  app-[]ₛ f a (γ ∘ₛ δ) = begin
    app f a [ γ ]ₛ [ δ ]ₛ                   ≡⟨ cong  x  x [ δ ]ₛ) (app-[]ₛ _ _ γ) 
    app (f [ γ ]ₛ) (a [ γ ]ₛ) [ δ ]ₛ        ≡⟨ app-[]ₛ _ _ δ 
    app (f [ γ ]ₛ [ δ ]ₛ) (a [ γ ]ₛ [ δ ]ₛ) 
  app-[]ₛ f a idₛ = refl

  lam-[]ₛ :
    (b : Tm (Γ  A) B) (γ : SSubs Δ Γ)  lam b [ γ ]ₛ  lam (b [ γ ⁺ₛ ]ₛ)
  lam-[]ₛ b  γ  = lam-[] _ _
  lam-[]ₛ b (γ ∘ₛ δ) = begin
    lam b [ γ ]ₛ [ δ ]ₛ         ≡⟨ cong  x  x [ δ ]ₛ) (lam-[]ₛ _ γ) 
    lam (b [ γ ⁺ₛ ]ₛ) [ δ ]ₛ    ≡⟨ lam-[]ₛ _ δ 
    lam (b [ γ ⁺ₛ ]ₛ [ δ ⁺ₛ ]ₛ) 
  lam-[]ₛ b idₛ = refl

  []-⁺ₛ→lam :
    (b : Tm (Γ  A) B) (γ : SSubs Δ Γ) 
    b [ γ ⁺ₛ ]ₛ  app (lam b [ γ ]ₛ [ p ]) q
  []-⁺ₛ→lam b γ = begin
    b [ γ ⁺ₛ ]ₛ                       ≡˘⟨ ▹-η _ 
    b [ γ ⁺ₛ ]ₛ [ p  ] [  q  ]     ≡˘⟨ ⇒-β _ _ 
    app (lam (b [ γ ⁺ₛ ]ₛ [ p  ])) q ≡˘⟨ cong  x  app x q) (lam-[]ₛ _ (γ ∘ₛ  p )) 
    app (lam b [ γ ]ₛ [ p ]) q        

  []-⁺ₛ :
    (b : Tm (Γ  A) B) (γ₀ γ₁ : SSubs Δ Γ) 
    (∀ {B} (b : Tm Γ B)  b [ γ₀ ]ₛ  b [ γ₁ ]ₛ)  b [ γ₀ ⁺ₛ ]ₛ  b [ γ₁ ⁺ₛ ]ₛ
  []-⁺ₛ b γ₀ γ₁ γ₀₁ = begin
    b [ γ₀ ⁺ₛ ]ₛ                ≡⟨ []-⁺ₛ→lam _ γ₀ 
    app (lam b [ γ₀ ]ₛ [ p ]) q ≡⟨ cong  x  app (x [ p ]) q) (γ₀₁ _) 
    app (lam b [ γ₁ ]ₛ [ p ]) q ≡˘⟨ []-⁺ₛ→lam _ γ₁ 
    b [ γ₁ ⁺ₛ ]ₛ                

  εₛ : SSubs Γ 
  εₛ {Γ = } = idₛ
  εₛ {Γ = Γ  A} = εₛ ∘ₛ  p 

  εₛ-[] : (a : Tm  A) (γ : SSub Δ Γ)  a [ εₛ ]ₛ [ γ ]  a [ εₛ ]ₛ
  εₛ-[] a pₛ = refl
  εₛ-[] a (γ ) = begin
    a [ εₛ ]ₛ [ p ] [ γ  ] ≡⟨ p-⁺ _ _ 
    a [ εₛ ]ₛ [ γ ] [ p ]   ≡⟨ cong  x  x [ p ]) (εₛ-[] _ _) 
    a [ εₛ ]ₛ [ p ]         
  εₛ-[] a  z  = p-⟨⟩ _ _

  ε-[]ₛ : (a : Tm  A) (γ : SSubs Δ Γ)  a [ εₛ ]ₛ [ γ ]ₛ  a [ εₛ ]ₛ
  ε-[]ₛ a  γ  = εₛ-[] _ _
  ε-[]ₛ a (γ ∘ₛ δ) = begin
    a [ εₛ ]ₛ [ γ ]ₛ [ δ ]ₛ ≡⟨ cong  x  x [ δ ]ₛ) (ε-[]ₛ _ γ) 
    a [ εₛ ]ₛ [ δ ]ₛ        ≡⟨ ε-[]ₛ _ δ 
    a [ εₛ ]ₛ               
  ε-[]ₛ a idₛ = refl

  infixl 4 _,ₜ_
  data Tms : Con  Con  Set where
    εₜ : Tms Γ 
    _,ₜ_ : Tms Δ Γ  Tm Δ A  Tms Δ (Γ  A)

  T→SS : Tms Δ Γ  SSubs Δ Γ
  T→SS εₜ = εₛ
  T→SS (γ ,ₜ a) = T→SS γ ⁺ₛ ∘ₛ   a  

  infixl 9 _[_]ₜ
  _[_]ₜ : Tm Γ A  Tms Δ Γ  Tm Δ A
  a [ γ ]ₜ = a [ T→SS γ ]ₛ

  infixl 9 _∘ₜ_
  _∘ₜ_ : Tms Δ Γ  Tms Θ Δ  Tms Θ Γ
  _∘ₜ_ εₜ δ = εₜ
  _∘ₜ_ (γ ,ₜ a) δ = γ ∘ₜ δ ,ₜ a [ δ ]ₜ

  []-∘ₜ :
    (a : Tm Γ A) (γ : Tms Δ Γ) (δ : Tms Θ Δ)  a [ γ ∘ₜ δ ]ₜ  a [ γ ]ₜ [ δ ]ₜ
  []-∘ₜ a εₜ δ = sym (ε-[]ₛ _ (T→SS δ))
  []-∘ₜ a (γ ,ₜ z) δ = begin
    a [ T→SS (γ ∘ₜ δ) ⁺ₛ ]ₛ [  z [ T→SS δ ]ₛ  ]         ≡⟨ cong  x  x [  z [ T→SS δ ]ₛ  ]) ([]-⁺ₛ _ (T→SS (γ ∘ₜ δ)) (T→SS γ ∘ₛ T→SS δ) λ a  []-∘ₜ _ γ δ) 
    a [ T→SS γ ⁺ₛ ]ₛ [ T→SS δ ⁺ₛ ]ₛ [  z [ T→SS δ ]ₛ  ] ≡˘⟨ ⟨⟩-[]ₛ _ _ (T→SS δ) 
    a [ T→SS γ ⁺ₛ ]ₛ [  z  ] [ T→SS δ ]ₛ                

  assocₜ :
    (γ : Tms Δ Γ) (δ : Tms Θ Δ) (θ : Tms Ξ Θ)  γ ∘ₜ (δ ∘ₜ θ)  γ ∘ₜ δ ∘ₜ θ
  assocₜ εₜ δ θ = refl
  assocₜ (γ ,ₜ a) δ θ = begin
    γ ∘ₜ (δ ∘ₜ θ) ,ₜ a [ δ ∘ₜ θ ]ₜ ≡⟨ cong  x  x ,ₜ a [ δ ∘ₜ θ ]ₜ) (assocₜ _ _ _) 
    γ ∘ₜ δ ∘ₜ θ ,ₜ a [ δ ∘ₜ θ ]ₜ   ≡⟨ cong  x  γ ∘ₜ δ ∘ₜ θ ,ₜ x) ([]-∘ₜ _ δ θ) 
    γ ∘ₜ δ ∘ₜ θ ,ₜ a [ δ ]ₜ [ θ ]ₜ 

  infixl 9 _∘pₜ
  _∘pₜ : Tms Δ Γ  Tms (Δ  A) Γ
  _∘pₜ εₜ = εₜ
  _∘pₜ (γ ,ₜ z) = γ ∘pₜ ,ₜ z [ p ]

  []-∘pₜ :
    (b : Tm Γ B) (γ : Tms Δ Γ)  (Tm (Δ  A) B  b [ γ ∘pₜ ]ₜ)  b [ γ ]ₜ [ p ]
  []-∘pₜ b εₜ = refl
  []-∘pₜ b (γ ,ₜ z) = begin
    b [ T→SS (γ ∘pₜ) ⁺ₛ ]ₛ [  z [ p ]  ]   ≡⟨ cong  x  x [  z [ p ]  ]) ([]-⁺ₛ _ (T→SS (γ ∘pₜ)) (T→SS γ ∘ₛ  p ) λ b  []-∘pₜ _ γ) 
    b [ T→SS γ ⁺ₛ ]ₛ [ p  ] [  z [ p ]  ] ≡˘⟨ ⟨⟩-[] _ _ _ 
    b [ T→SS γ ⁺ₛ ]ₛ [  z  ] [ p ]         

  ∘p-,ₜ : (γ : Tms Δ Γ) (δ : Tms Θ Δ) (a : Tm Θ A)  γ ∘pₜ ∘ₜ (δ ,ₜ a)  γ ∘ₜ δ
  ∘p-,ₜ εₜ δ a = refl
  ∘p-,ₜ (γ ,ₜ z) δ a = begin
    γ ∘pₜ ∘ₜ (δ ,ₜ a) ,ₜ z [ p ] [ T→SS δ ⁺ₛ ]ₛ [  a  ] ≡⟨ cong  x  x ,ₜ z [ p ] [ T→SS δ ⁺ₛ ]ₛ [  a  ]) (∘p-,ₜ _ _ _) 
    γ ∘ₜ δ ,ₜ z [ p ] [ T→SS δ ⁺ₛ ]ₛ [  a  ]            ≡⟨ cong  x  γ ∘ₜ δ ,ₜ x [  a  ]) (p-⁺ₛ _ (T→SS δ)) 
    γ ∘ₜ δ ,ₜ z [ T→SS δ ]ₛ [ p ] [  a  ]               ≡⟨ cong  x  γ ∘ₜ δ ,ₜ x) (p-⟨⟩ _ _) 
    γ ∘ₜ δ ,ₜ z [ T→SS δ ]ₛ                               

  idₜ : Tms Γ Γ
  idₜ {Γ = } = εₜ
  idₜ {Γ = Γ  A} = idₜ ∘pₜ ,ₜ q

  []-idₜ : (a : Tm Γ A)  a [ idₜ ]ₜ  a
  []-idₜ {Γ = } a = refl
  []-idₜ {Γ = Γ  Z} a = begin
    a [ T→SS (idₜ ∘pₜ) ⁺ₛ ]ₛ [  q  ]   ≡⟨ cong  x  x [  q  ]) ([]-⁺ₛ a (T→SS (idₜ ∘pₜ)) (T→SS idₜ ∘ₛ  p ) λ a  []-∘pₜ _ idₜ) 
    a [ T→SS idₜ ⁺ₛ ]ₛ [ p  ] [  q  ] ≡⟨ cong  x  x [ p  ] [  q  ]) ([]-⁺ₛ _ (T→SS idₜ) idₛ λ a  []-idₜ _) 
    a [ p  ] [  q  ]                  ≡⟨ ▹-η _ 
    a                                    

  idrₜ : (γ : Tms Δ Γ)  γ ∘ₜ idₜ  γ
  idrₜ εₜ = refl
  idrₜ (γ ,ₜ a) = begin
    γ ∘ₜ idₜ ,ₜ a [ idₜ ]ₜ ≡⟨ cong  x  x ,ₜ a [ idₜ ]ₜ) (idrₜ _) 
    γ ,ₜ a [ idₜ ]ₜ        ≡⟨ cong  x  γ ,ₜ x) ([]-idₜ _) 
    γ ,ₜ a                 

  idlₜ : (γ : Tms Δ Γ)  idₜ ∘ₜ γ  γ
  idlₜ εₜ = refl
  idlₜ (γ ,ₜ a) = begin
    idₜ ∘pₜ ∘ₜ (γ ,ₜ a) ,ₜ q [ T→SS γ ⁺ₛ ]ₛ [  a  ] ≡⟨ cong  x  x ,ₜ q [ T→SS γ ⁺ₛ ]ₛ [  a  ]) (∘p-,ₜ _ _ _) 
    idₜ ∘ₜ γ ,ₜ q [ T→SS γ ⁺ₛ ]ₛ [  a  ]            ≡⟨ cong  x  x ,ₜ q [ T→SS γ ⁺ₛ ]ₛ [  a  ]) (idlₜ _) 
    γ ,ₜ q [ T→SS γ ⁺ₛ ]ₛ [  a  ]                   ≡⟨ cong  x  γ ,ₜ x [  a  ]) (q-⁺ₛ (T→SS γ)) 
    γ ,ₜ q [  a  ]                                  ≡⟨ cong  x  γ ,ₜ x) (q-⟨⟩ _) 
    γ ,ₜ a                                            

module _ (M : SSC) where
  open SSC M
  open SSC→CwF M

  SSC→CwF : CwF
  SSC→CwF .CwF.Ty = Ty
  SSC→CwF .CwF.Sub = Tms

  SSC→CwF .CwF._∘_ = _∘ₜ_
  SSC→CwF .CwF.assoc = assocₜ

  SSC→CwF .CwF.id = idₜ
  SSC→CwF .CwF.idr = idrₜ
  SSC→CwF .CwF.idl = idlₜ

  SSC→CwF .CwF.Tm = Tm
  SSC→CwF .CwF._[_] = _[_]ₜ
  SSC→CwF .CwF.[]-∘ = []-∘ₜ
  SSC→CwF .CwF.[]-id = []-idₜ

  SSC→CwF .CwF.ε = εₜ
  SSC→CwF .CwF.ε-∘ γ = refl
  SSC→CwF .CwF.◆-η = refl

  SSC→CwF .CwF.p = idₜ ∘pₜ
  SSC→CwF .CwF.q = q

  SSC→CwF .CwF._,_ = _,ₜ_
  SSC→CwF .CwF.,-∘ γ a δ = refl

  SSC→CwF .CwF.▹-β₁ γ a = begin
    idₜ ∘pₜ ∘ₜ (γ ,ₜ a) ≡⟨ ∘p-,ₜ _ _ _ 
    idₜ ∘ₜ γ            ≡⟨ idlₜ _ 
    γ                   
  SSC→CwF .CwF.▹-β₂ γ a = begin
    q [ T→SS γ ⁺ₛ ]ₛ [  a  ] ≡⟨ cong  x  x [  a  ]) (q-⁺ₛ (T→SS γ)) 
    q [  a  ]                ≡⟨ q-⟨⟩ _ 
    a                          
  SSC→CwF .CwF.▹-η = refl

  SSC→CwF .CwF.ι = ι
  SSC→CwF .CwF._⇒_ = _⇒_

  SSC→CwF .CwF.app = app
  SSC→CwF .CwF.app-[] f a γ = app-[]ₛ _ _ (T→SS γ)

  SSC→CwF .CwF.lam = lam
  SSC→CwF .CwF.lam-[] b γ = begin
    lam b [ T→SS γ ]ₛ                                         ≡⟨ lam-[]ₛ _ (T→SS γ) 
    lam (b [ T→SS γ ⁺ₛ ]ₛ)                                    ≡˘⟨ cong  x  lam x) ([]-⁺ₛ _ (T→SS idₜ) idₛ λ b  []-idₜ _) 
    lam (b [ T→SS γ ⁺ₛ ]ₛ [ T→SS idₜ ⁺ₛ ]ₛ)                   ≡˘⟨ cong  x  lam x) (▹-η _) 
    lam (b [ T→SS γ ⁺ₛ ]ₛ [ T→SS idₜ ⁺ₛ ]ₛ [ p  ] [  q  ]) ≡˘⟨ cong  x  lam (x [  q  ])) ([]-⁺ₛ (b [ T→SS γ ⁺ₛ ]ₛ) (T→SS (idₜ ∘pₜ)) (T→SS idₜ ∘ₛ  p ) λ b  []-∘pₜ _ idₜ) 
    lam (b [ T→SS γ ⁺ₛ ]ₛ [ T→SS (idₜ ∘pₜ) ⁺ₛ ]ₛ [  q  ])   ≡˘⟨ cong  x  lam (x [  q  ])) ([]-⁺ₛ _ (T→SS (γ ∘ₜ (idₜ ∘pₜ))) (T→SS γ ∘ₛ T→SS (idₜ ∘pₜ)) λ b  []-∘ₜ _ γ (idₜ ∘pₜ)) 
    lam (b [ T→SS (γ ∘ₜ (idₜ ∘pₜ)) ⁺ₛ ]ₛ [  q  ])           

  SSC→CwF .CwF.⇒-β b a = begin
    app (lam b) a                ≡⟨ ⇒-β _ _ 
    b [  a  ]                  ≡˘⟨ cong  x  x [  a  ]) ([]-⁺ₛ _ (T→SS idₜ) idₛ λ b  []-idₜ _) 
    b [ T→SS idₜ ⁺ₛ ]ₛ [  a  ] 
  SSC→CwF .CwF.⇒-η f = begin
    lam (app (f [ T→SS (idₜ ∘pₜ) ]ₛ) q) ≡⟨ cong  x  lam (app x q)) ([]-∘pₜ _ idₜ) 
    lam (app (f [ T→SS idₜ ]ₛ [ p ]) q) ≡⟨ cong  x  lam (app (x [ p ]) q)) ([]-idₜ _) 
    lam (app (f [ p ]) q)               ≡⟨ ⇒-η _ 
    f                                   

module SSC→CwF→SSC (M : SSC) where
  open SSC M
  open SSC→CwF M
  open CwF→SSC (SSC→CwF M) hiding (SSub)
  module SCS = SSC (CwF→SSC (SSC→CwF M))

  private variable
    Γ Δ : Con
    A B : Ty

  SCS-Ty : SCS.Ty  Ty
  SCS-Ty = refl

  SCS-Tm : (Γ : Con) (A : Ty)  SCS.Tm Γ A  Tm Γ A
  SCS-Tm Γ A = refl

  SCS-[] : (a : Tm Γ A) (γ : SSub Δ Γ)  a SCS.[ γ ]  a [ γ ]
  SCS-[] a pₛ = begin
    a [ idₜ ∘pₜ ]ₜ   ≡⟨ []-∘pₜ _ idₜ 
    a [ idₜ ]ₜ [ p ] ≡⟨ cong  x  x [ p ]) ([]-idₜ _) 
    a [ p ]          
  SCS-[] a (γ ) = begin
    a [ T→SS (SS→S γ ∘ₜ (idₜ ∘pₜ)) ⁺ₛ ]ₛ [  q  ]           ≡⟨ cong  x  x [  q  ]) ([]-⁺ₛ _ (T→SS (SS→S γ ∘ₜ (idₜ ∘pₜ))) (T→SS (SS→S γ) ∘ₛ (T→SS (idₜ ∘pₜ))) λ a  []-∘ₜ _ (SS→S γ) (idₜ ∘pₜ)) 
    a [ T→SS (SS→S γ) ⁺ₛ ]ₛ [ T→SS (idₜ ∘pₜ) ⁺ₛ ]ₛ [  q  ] ≡⟨ cong  x  x [ T→SS (idₜ ∘pₜ) ⁺ₛ ]ₛ [  q  ]) ([]-⁺ₛ _ (T→SS (SS→S γ))  γ  λ a  SCS-[] _ _) 
    a [ γ  ] [ T→SS (idₜ ∘pₜ) ⁺ₛ ]ₛ [  q  ]               ≡⟨ cong  x  x [  q  ]) ([]-⁺ₛ _ (T→SS (idₜ ∘pₜ)) (T→SS idₜ ∘ₛ  p ) λ a  []-∘pₜ _ idₜ) 
    a [ γ  ] [ T→SS idₜ ⁺ₛ ]ₛ [ p  ] [  q  ]             ≡⟨ cong  x  x [ p  ] [  q  ]) ([]-⁺ₛ _ (T→SS idₜ) idₛ λ a  []-idₜ _) 
    a [ γ  ] [ p  ] [  q  ]                              ≡⟨ ▹-η _ 
    a [ γ  ]                                                
  SCS-[] a  z  =
    cong  x  x [  z  ]) ([]-⁺ₛ _ (T→SS idₜ) idₛ λ a  []-idₜ _)

  SCS-q : (Tm (Γ  A) A  SCS.q)  q
  SCS-q = refl

  SCS-ι : SCS.ι  ι
  SCS-ι = refl

  SCS-⇒ : (A B : Ty)  (A SCS.⇒ B)  (A  B)
  SCS-⇒ A B = refl

  SCS-app : (f : Tm Γ (A  B)) (a : Tm Γ A)  SCS.app f a  app f a
  SCS-app f a = refl

  SCS-lam : (b : Tm (Γ  A) B)  SCS.lam b  lam b
  SCS-lam b = refl

module CwF→SSC→CwF (M : CwF) where
  open CwF M
  open CwF→SSC M
  open SSC→CwF (CwF→SSC M)
  module CSC = CwF (SSC→CwF (CwF→SSC M))

  private variable
    Γ Δ Θ : Con
    A B : Ty

  CSC-Ty : CSC.Ty  Ty
  CSC-Ty = refl

  CSC-Tm : (Γ : Con) (A : Ty)  CSC.Tm Γ A  Tm Γ A
  CSC-Tm Γ A = refl

  T→S : Tms Δ Γ  Sub Δ Γ
  T→S εₜ = ε
  T→S (γ ,ₜ a) = T→S γ , a

  S→T : Sub Δ Γ  Tms Δ Γ
  S→T {Γ = } γ = εₜ
  S→T {Γ = Γ  A} γ = S→T (p  γ) ,ₜ q [ γ ]

  S→T→S : (γ : Sub Δ Γ)  T→S (S→T γ)  γ
  S→T→S {Γ = } γ = begin
    ε      ≡˘⟨ ε-∘ _ 
    ε  γ  ≡⟨ cong  x  x  γ) ◆-η 
    id  γ ≡⟨ idl _ 
    γ      
  S→T→S {Γ = Γ  A} γ = begin
    T→S (S→T (p  γ)) , q [ γ ] ≡⟨ cong  x  x , q [ γ ]) (S→T→S _) 
    p  γ , q [ γ ]             ≡˘⟨ ,-∘ _ _ _ 
    (p , q)  γ                 ≡⟨ cong  x  x  γ) ▹-η 
    id  γ                      ≡⟨ idl _ 
    γ                           

  T→S→T : (γ : Tms Δ Γ)  S→T (T→S γ)  γ
  T→S→T εₜ = refl
  T→S→T (γ ,ₜ a) = begin
    S→T (p  (T→S γ , a)) ,ₜ q [ T→S γ , a ] ≡⟨ cong  x  S→T x ,ₜ q [ T→S γ , a ]) (▹-β₁ _ _) 
    S→T (T→S γ) ,ₜ q [ T→S γ , a ]           ≡⟨ cong  x  x ,ₜ q [ T→S γ , a ]) (T→S→T _) 
    γ ,ₜ q [ T→S γ , a ]                     ≡⟨ cong  x  γ ,ₜ x) (▹-β₂ _ _) 
    γ ,ₜ a                                   

  CSC-Sub : (Δ Γ : Con)  CSC.Sub Δ Γ  Sub Δ Γ
  CSC-Sub Δ Γ = mk↔ₛ′ T→S S→T S→T→S T→S→T

  []-εₛ : (a : Tm  A)  (Tm Γ A  a [ εₛ ]ₛ)  a [ ε ]
  []-εₛ {Γ = } a = begin
    a        ≡˘⟨ []-id _ 
    a [ id ] ≡˘⟨ cong  x  a [ x ]) ◆-η 
    a [ ε ]  
  []-εₛ {Γ = Γ  Z} a = begin
    a [ εₛ ]ₛ [ p ] ≡⟨ cong  x  x [ p ]) ([]-εₛ _) 
    a [ ε ] [ p ]   ≡˘⟨ []-∘ _ _ _ 
    a [ ε  p ]     ≡⟨ cong  x  a [ x ]) (ε-∘ _) 
    a [ ε ]         

  CSC-[] : (a : Tm Γ A) (γ : Tms Δ Γ)  a CSC.[ γ ]  a [ T→S γ ]
  CSC-[] a εₜ = []-εₛ _
  CSC-[] a (γ ,ₜ z) = begin
    a [ T→SS γ ⁺ₛ ]ₛ [ id , z ]                           ≡⟨ cong  x  x [ id , z ]) ([]-⁺ₛ→lam _ (T→SS γ)) 
    app (lam a [ T→SS γ ]ₛ [ p ]) q [ id , z ]            ≡⟨ cong  x  app (x [ p ]) q [ id , z ]) (CSC-[] _ γ) 
    app (lam a [ T→S γ ] [ p ]) q [ id , z ]              ≡⟨ app-[] _ _ _ 
    app (lam a [ T→S γ ] [ p ] [ id , z ]) (q [ id , z ]) ≡˘⟨ cong  x  app x (q [ id , z ])) ([]-∘ _ _ _) 
    app (lam a [ T→S γ ] [ p  (id , z) ]) (q [ id , z ]) ≡⟨ cong  x  app (lam a [ T→S γ ] [ x ]) (q [ id , z ])) (▹-β₁ _ _) 
    app (lam a [ T→S γ ] [ id ]) (q [ id , z ])           ≡⟨ cong  x  app x (q [ id , z ])) ([]-id _) 
    app (lam a [ T→S γ ]) (q [ id , z ])                  ≡⟨ cong  x  app (lam a [ T→S γ ]) x) (▹-β₂ _ _) 
    app (lam a [ T→S γ ]) z                               ≡⟨ cong  x  app x z) (lam-[] _ _) 
    app (lam (a [ T→S γ  p , q ])) z                     ≡⟨ ⇒-β _ _ 
    a [ T→S γ  p , q ] [ id , z ]                        ≡˘⟨ []-∘ _ _ _ 
    a [ (T→S γ  p , q)  (id , z) ]                      ≡⟨ cong  x  a [ x ]) (,-∘ _ _ _) 
    a [ T→S γ  p  (id , z) , q [ id , z ] ]             ≡˘⟨ cong  x  a [ x , q [ id , z ] ]) (assoc _ _ _) 
    a [ T→S γ  (p  (id , z)) , q [ id , z ] ]           ≡⟨ cong  x  a [ T→S γ  x , q [ id , z ] ]) (▹-β₁ _ _) 
    a [ T→S γ  id , q [ id , z ] ]                       ≡⟨ cong  x  a [ x , q [ id , z ] ]) (idr _) 
    a [ T→S γ , q [ id , z ] ]                            ≡⟨ cong  x  a [ T→S γ , x ]) (▹-β₂ _ _) 
    a [ T→S γ , z ]                                       

  CSC-∘ : (γ : Tms Δ Γ) (δ : Tms Θ Δ)  T→S (γ CSC.∘ δ)  T→S γ  T→S δ
  CSC-∘ εₜ δ = sym (ε-∘ _)
  CSC-∘ (γ ,ₜ a) δ = begin
    T→S (γ ∘ₜ δ) , a [ δ ]ₜ     ≡⟨ cong  x  x , a [ δ ]ₜ) (CSC-∘ γ δ) 
    T→S γ  T→S δ , a [ δ ]ₜ    ≡⟨ cong  x  T→S γ  T→S δ , x) (CSC-[] _ δ) 
    T→S γ  T→S δ , a [ T→S δ ] ≡˘⟨ ,-∘ _ _ _ 
    (T→S γ , a)  T→S δ         

  CSC-∘p : (γ : Tms Δ Γ)  (Sub (Δ  A) Γ  T→S (γ ∘pₜ))  (T→S γ  p)
  CSC-∘p εₜ = sym (ε-∘ _)
  CSC-∘p (γ ,ₜ z) = begin
    T→S (γ ∘pₜ) , z [ p ] ≡⟨ cong  x  x , z [ p ]) (CSC-∘p γ) 
    T→S γ  p , z [ p ]   ≡˘⟨ ,-∘ _ _ _ 
    (T→S γ , z)  p       

  CSC-id : (Sub Γ Γ  T→S CSC.id)  id
  CSC-id {Γ = } = ◆-η
  CSC-id {Γ = Γ  A} = begin
    T→S (idₜ ∘pₜ) , q ≡⟨ cong  x  x , q) (CSC-∘p idₜ) 
    T→S idₜ  p , q   ≡⟨ cong  x  x  p , q) CSC-id 
    id  p , q        ≡⟨ cong  x  x , q) (idl _) 
    p , q             ≡⟨ ▹-η 
    id                

  CSC-ε : (Sub Γ   T→S CSC.ε)  ε
  CSC-ε = refl

  CSC-p : (Sub (Γ  A) Γ  T→S CSC.p)  p
  CSC-p = begin
    T→S (idₜ ∘pₜ) ≡⟨ CSC-∘p idₜ 
    T→S idₜ  p   ≡⟨ cong  x  x  p) CSC-id 
    id  p        ≡⟨ idl _ 
    p             

  CSC-q : (Tm (Γ  A) A  CSC.q)  q
  CSC-q = refl

  CSC-, : (γ : Tms Δ Γ) (a : Tm Δ A)  T→S (γ CSC., a)  (T→S γ , a)
  CSC-, γ a = refl

  CSC-ι : CSC.ι  ι
  CSC-ι = refl

  CSC-⇒ : (A B : Ty)  (A CSC.⇒ B)  (A  B)
  CSC-⇒ A B = refl

  CSC-app : (f : Tm Γ (A  B)) (a : Tm Γ A)  CSC.app f a  app f a
  CSC-app f a = refl

  CSC-lam : (b : Tm (Γ  A) B)  CSC.lam b  lam b
  CSC-lam b = refl