module A201605.AbelChapmanExtended2.RenamingLemmas.Normalization1 where

open import Relation.Binary.PropositionalEquality using (_≡_ ; refl ; sym ; cong)

open import A201605.AbelChapmanExtended.Delay
open import A201605.AbelChapmanExtended.StrongBisimilarity

open import A201605.AbelChapmanExtended2.Syntax
open import A201605.AbelChapmanExtended2.OPE
open import A201605.AbelChapmanExtended2.Renaming
open import A201605.AbelChapmanExtended2.Normalization
open import A201605.AbelChapmanExtended2.RenamingLemmas.OPE




ren-lookup :  {Γ Δ Δ′ a} (η : Δ′  Δ) (x : Var Γ a) (ρ : Env Δ Γ) 
             ren-val η (lookup x ρ)  lookup x (ren-env η ρ)
ren-lookup η top     (ρ , v) = refl
ren-lookup η (pop x) (ρ , v) = ren-lookup η x ρ


ren-π₁-reduce :  {i Δ Δ′ a b} (η : Δ′  Δ) (v : Val Δ (a  b)) 
                ren-val η <$> π₁-reduce v ≈⟨ i ⟩≈ π₁-reduce (ren-val η v)
ren-π₁-reduce η (ne v)     = ≈refl
ren-π₁-reduce η (pair v w) = ≈refl


ren-π₂-reduce :  {i Δ Δ′ a b} (η : Δ′  Δ) (v : Val Δ (a  b)) 
                ren-val η <$> π₂-reduce v ≈⟨ i ⟩≈ π₂-reduce (ren-val η v)
ren-π₂-reduce η (ne v)     = ≈refl
ren-π₂-reduce η (pair v w) = ≈refl


ren-ω-reduce :  {i Δ Δ′ a} (η : Δ′  Δ) (v : Val Δ ) 
               ren-val η <$> ω-reduce v ≈⟨ i ⟩≈ ω-reduce {a = a} (ren-val η v)
ren-ω-reduce η (ne v)     = ≈refl


mutual
  ren-eval :  {i Γ Δ Δ′ a} (η : Δ′  Δ) (t : Tm Γ a) (ρ : Env Δ Γ) 
             ren-val η <$> eval t ρ ≈⟨ i ⟩≈ eval t (ren-env η ρ)
  ren-eval η (boom t) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         ω-reduce v)
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> ω-reduce v
    ≈⟨ v  eval t ρ 
       ren-ω-reduce η v 
          v  eval t ρ 
          ω-reduce (ren-val η v)
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          ω-reduce v′
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          ω-reduce v′
    
    where open ≈-Reasoning
  ren-eval η (inl t) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         now (inl v))
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> now (inl v)
    ≈⟨ v  eval t ρ 
       ≈now (inl (ren-val η v)) 
          v  eval t ρ 
          now (inl (ren-val η v))
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          now (inl v′)
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          now (inl v′)
    
    where open ≈-Reasoning
  ren-eval η (inr t) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         now (inr v))
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> now (inr v)
    ≈⟨ v  eval t ρ 
       ≈now (inr (ren-val η v)) 
          v  eval t ρ 
          now (inr (ren-val η v))
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          now (inr v′)
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          now (inr v′)
    
    where open ≈-Reasoning
  ren-eval η (case t ul ur) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         κ-reduce v ul ur ρ)
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> κ-reduce v ul ur ρ
    ≈⟨ v  eval t ρ 
       ren-κ-reduce η v ul ur ρ 
          v  eval t ρ 
          κ-reduce (ren-val η v) ul ur (ren-env η ρ)
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          κ-reduce v′ ul ur (ren-env η ρ)
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          κ-reduce v′ ul ur (ren-env η ρ)
    
    where open ≈-Reasoning
  ren-eval η (var x)   ρ rewrite ren-lookup η x ρ = ≈now (lookup x (ren-env η ρ))
  ren-eval η (lam t)   ρ = ≈now (lam t (ren-env η ρ))
  ren-eval η (app t u) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         w  eval u ρ 
                         β-reduce v w)
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> (w  eval u ρ 
                         β-reduce v w)
    ≈⟨ v  eval t ρ 
        eval u ρ 
          v  eval t ρ 
          w  eval u ρ 
          ren-val η <$> β-reduce v w
    ≈⟨ v  eval t ρ 
       w  eval u ρ 
       ren-β-reduce η v w 
          v  eval t ρ 
          w  eval u ρ 
          β-reduce (ren-val η v) (ren-val η w)
    ≈⟨ v  eval t ρ 
        eval u ρ 
          v   eval t ρ 
          w′  ren-val η <$> eval u ρ 
          β-reduce (ren-val η v) w′
     v  eval t ρ 
        ren-eval η u ρ 
          v   eval t ρ 
          w′  eval u (ren-env η ρ) 
          β-reduce (ren-val η v) w′
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          w′  eval u (ren-env η ρ) 
          β-reduce v′ w′
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          w′  eval u (ren-env η ρ) 
          β-reduce v′ w′
    
    where open ≈-Reasoning
  ren-eval η (pair t u) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         w  eval u ρ 
                         now (pair v w))
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> (w  eval u ρ 
                         now (pair v w))
    ≈⟨ v  eval t ρ 
        eval u ρ 
          v  eval t ρ 
          w  eval u ρ 
          ren-val η <$> now (pair v w)
    ≈⟨ v  eval t ρ 
       w  eval u ρ 
       ≈now (pair (ren-val η v) (ren-val η w)) 
          v  eval t ρ 
          w  eval u ρ 
          now (pair (ren-val η v) (ren-val η w))
    ≈⟨ v  eval t ρ 
        eval u ρ 
          v   eval t ρ 
          w′  ren-val η <$> eval u ρ 
          now (pair (ren-val η v) w′)
    ≈⟨ v  eval t ρ 
        ren-eval η u ρ 
          v   eval t ρ 
          w′  eval u (ren-env η ρ) 
          now (pair (ren-val η v) w′)
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          w′  eval u (ren-env η ρ) 
          now (pair v′ w′)
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          w′  eval u (ren-env η ρ) 
          now (pair v′ w′)
    
    where open ≈-Reasoning
  ren-eval η (fst t) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         π₁-reduce v)
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> π₁-reduce v
    ≈⟨ v  eval t ρ 
       ren-π₁-reduce η v 
          v  eval t ρ 
          π₁-reduce (ren-val η v)
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          π₁-reduce v′
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          π₁-reduce v′
    
    where open ≈-Reasoning
  ren-eval η (snd t) ρ =
    proof
          ren-val η <$> (v  eval t ρ 
                         π₂-reduce v)
    ≈⟨  eval t ρ 
          v  eval t ρ 
          ren-val η <$> π₂-reduce v
    ≈⟨ v  eval t ρ 
       ren-π₂-reduce η v 
          v  eval t ρ 
          π₂-reduce (ren-val η v)
    ≈⟨  eval t ρ 
          v′  ren-val η <$> eval t ρ 
          π₂-reduce v′
    ≈⟨  ren-eval η t ρ 
          v′  eval t (ren-env η ρ) 
          π₂-reduce v′
    
    where open ≈-Reasoning
  ren-eval η unit ρ = ≈now unit


  ren-∞eval :  {i Γ Δ Δ′ a} (η : Δ′  Δ) (t : Tm Γ a) (ρ : Env Δ Γ) 
              ren-val η ∞<$> ∞eval t ρ ∞≈⟨ i ⟩≈ ∞eval t (ren-env η ρ)
  ≈force (ren-∞eval η t ρ) = ren-eval η t ρ


  ren-κ-reduce :  {i Γ Δ′ Δ a b c} (η : Δ′  Δ) (v : Val Δ (a  b))
                 (ul : Tm (Γ , a) c) (ur : Tm (Γ , b) c) (ρ : Env Δ Γ) 
                 ren-val η <$> κ-reduce v ul ur ρ ≈⟨ i ⟩≈
                 κ-reduce (ren-val η v) ul ur (ren-env η ρ)
  ren-κ-reduce η (ne v)  ul ur ρ =
    proof
          ren-val η <$> (wl  eval ul (wk-env ρ , nev₀) 
                         wr  eval ur (wk-env ρ , nev₀) 
                         now (ne (case v wl wr)))
    ≈⟨  eval ul (wk-env ρ , nev₀) 
          wl  eval ul (wk-env ρ , nev₀) 
          ren-val η <$> (wr  eval ur (wk-env ρ , nev₀) 
                         now (ne (case v wl wr)))
    ≈⟨ wl  eval ul (wk-env ρ , nev₀) 
        eval ur (wk-env ρ , nev₀) 
          wl  eval ul (wk-env ρ , nev₀) 
          wr  eval ur (wk-env ρ , nev₀) 
          ren-val η <$> now (ne (case v wl wr))
    ≈⟨ wl  eval ul (wk-env ρ , nev₀) 
       wr  eval ur (wk-env ρ , nev₀) 
       ≈now (ne (ren-nev η (case v wl wr))) 
          wl  eval ul (wk-env ρ , nev₀) 
          wr  eval ur (wk-env ρ , nev₀) 
          now (ne (ren-nev η (case v wl wr)))
    ≡⟨⟩
          wl  eval ul (wk-env ρ , nev₀) 
          wr  eval ur (wk-env ρ , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) (ren-val (lift η) wr)))
    ≈⟨ wl  eval ul (wk-env ρ , nev₀) 
        eval ur (wk-env ρ , nev₀) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  ren-val (lift η) <$> eval ur (wk-env ρ , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≈⟨ wl  eval ul (wk-env ρ , nev₀) 
        ren-eval (lift η) ur (wk-env ρ , nev₀) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (ren-env (lift η) (wk-env ρ) , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≡⟨ cong  ρ′  (wl   eval ul (wk-env ρ , nev₀) 
                      wr′  eval ur (ρ′ , nev₀) 
                      now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))))
            (ren-env-• (lift η) wk ρ) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (ren-env (weak (η  id)) ρ , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≡⟨ cong  η′  (wl   eval ul (wk-env ρ , nev₀) 
                      wr′  eval ur (ren-env (weak η′) ρ , nev₀) 
                      now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))))
            (η•id η) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (ren-env (weak η) ρ , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≡⟨ cong  η′  (wl   eval ul (wk-env ρ , nev₀) 
                      wr′  eval ur (ren-env (weak η′) ρ , nev₀) 
                      now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))))
            (sym (id•η η)) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (ren-env (weak (id  η)) ρ , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≡⟨ cong  ρ′  (wl   eval ul (wk-env ρ , nev₀) 
                      wr′  eval ur (ρ′ , nev₀) 
                      now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))))
            (sym (ren-env-• wk η ρ)) 
          wl   eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) (ren-val (lift η) wl) wr′))
    ≈⟨  eval ul (wk-env ρ , nev₀) 
          wl′  ren-val (lift η) <$> eval ul (wk-env ρ , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    ≈⟨  ren-eval (lift η) ul (wk-env ρ , nev₀) 
          wl′  eval ul (ren-env (lift η) (wk-env ρ) , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    ≡⟨ cong  ρ′  (wl′  eval ul (ρ′ , nev₀) 
                      wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
                      now (ne (case (ren-nev η v) wl′ wr′))))
            (ren-env-• (lift η) wk ρ) 
          wl′  eval ul (ren-env (weak (η  id)) ρ , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    ≡⟨ cong  η′  (wl′  eval ul (ren-env (weak η′) ρ , nev₀) 
                      wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
                      now (ne (case (ren-nev η v) wl′ wr′))))
            (η•id η) 
          wl′  eval ul (ren-env (weak η) ρ , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    ≡⟨ cong  η′  (wl′  eval ul (ren-env (weak η′) ρ , nev₀) 
                      wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
                      now (ne (case (ren-nev η v) wl′ wr′))))
            (sym (id•η η)) 
          wl′  eval ul (ren-env (weak (id  η)) ρ , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    ≡⟨ cong  ρ′  (wl′  eval ul (ρ′ , nev₀) 
                      wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
                      now (ne (case (ren-nev η v) wl′ wr′))))
            (sym (ren-env-• wk η ρ)) 
          wl′  eval ul (wk-env (ren-env η ρ) , nev₀) 
          wr′  eval ur (wk-env (ren-env η ρ) , nev₀) 
          now (ne (case (ren-nev η v) wl′ wr′))
    
    where open ≈-Reasoning
  ren-κ-reduce η (inl v) ul ur ρ = ≈later (ren-∞eval η ul (ρ , v))
  ren-κ-reduce η (inr v) ul ur ρ = ≈later (ren-∞eval η ur (ρ , v))


  ren-β-reduce :  {i Δ Δ′ a b} (η : Δ′  Δ) (v : Val Δ (a  b)) (w : Val Δ a) 
                 ren-val η <$> β-reduce v w ≈⟨ i ⟩≈ β-reduce (ren-val η v) (ren-val η w)
  ren-β-reduce η (ne v)    w = ≈refl
  ren-β-reduce η (lam t ρ) w = ≈later (ren-∞eval η t (ρ , w))