{-# OPTIONS --safe #-}
module CtxTyp.Substitution where

open import Function.Base using (id)

open import Data.Nat.Base using (; suc; zero)

open import CtxTyp.Context
open import CtxTyp.Term
open import CtxTyp.Depth

substᵈ :  {d} {σ : Subst Γ Γ′}  σ ≤ᵈ′ d  Term n Γ A  Term n Γ′ A
substSubstᵈ :  {d} {σ : Subst Γ Γ′}  σ ≤ᵈ′ d  Subst Δ Γ  Subst Δ Γ′

substᵈ {σ = σ} σᵈ (` x `with σ′) with lookup σ x | lookupᵈ σᵈ x | substSubstᵈ σᵈ σ′
substᵈ {σ = σ} σᵈ (` x `with σ′)             | var y  | _        | σσ′ = ` y `with σσ′
substᵈ {d = suc _} {σ = σ} σᵈ (` x `with σ′) | term e | term-Δ<d | σσ′ = substᵈ (liftᵈ id ++ˢᵈ σσ′ᵈ) e
  where σσ′ᵈ = ≤ᵈ-dom σσ′ (untermᵈ term-Δ<d)
substᵈ σᵈ `true = `true
substᵈ σᵈ `false = `false
substᵈ σᵈ (`if e₁ `then e₂ `else e₃) = `if substᵈ σᵈ e₁ `then substᵈ σᵈ e₂ `else substᵈ σᵈ e₃
substᵈ σᵈ (`λ⟨ Δ  e) = `λ⟨ Δ  substᵈ (extsᵈ σᵈ) e
substᵈ σᵈ (e₁ · e₂) = substᵈ σᵈ e₁ · substᵈ (exts++ᵈ _ σᵈ) e₂
substᵈ σᵈ  e  =  substᵈ (exts↾ᵈ σᵈ) e 
substᵈ σᵈ (`let⟨ Δ  e₁ e₂) = `let⟨ Δ  (substᵈ (exts++ᵈ (inject₁ Δ) σᵈ) e₁) (substᵈ (extsᵈ σᵈ) e₂)
substᵈ σᵈ (`wrap Δ e) = `wrap Δ (substᵈ (exts++ᵈ (inject₁ Δ) σᵈ) e)
substᵈ σᵈ (`letwrap Δ e₁ e₂) = `letwrap Δ (substᵈ σᵈ e₁) (substᵈ (extsᵈ σᵈ) e₂)
 
substSubstᵈ σᵈ  = 
substSubstᵈ {Δ = Δ ,[ Δ′  A ^ m≥n ]} σᵈ (σ′ , term e) = substSubstᵈ σᵈ σ′ , term (substᵈ (exts++ᵈ Δ′ (exts↾≥ᵈ m≥n σᵈ)) e)
substSubstᵈ {σ = σ} σᵈ (σ′ , var x) = substSubstᵈ σᵈ σ′ , lookup σ x

substᵈ[_] :  {d} (σ : Subst Γ Γ′)  σ ≤ᵈ′ d  Term n Γ A  Term n Γ′ A
substᵈ[ σ ] = substᵈ {σ = σ}

{-# DISPLAY substᵈ {σ = σ} = substᵈ[ σ ] #-}

subst : Subst Γ Γ′  Term n Γ A  Term n Γ′ A
subst σ = substᵈ (≤ᵈ′-refl σ)

substSubst : Subst Γ Γ′  Subst Δ Γ  Subst Δ Γ′
substSubst σ = substSubstᵈ (≤ᵈ′-refl σ)