module A201607.WIP.BasicIPC.Syntax.GentzenNormalFormN where

open import A201607.BasicIPC.Syntax.Gentzen public

open import Data.Nat using (_+_)


mutual
  infix 3 _⊢ⁿᶠ[_]_
  data _⊢ⁿᶠ[_]_ (Γ : Cx Ty) :   Ty  Set where
    neⁿᶠ   :  {A k}      Γ ⊢ⁿᵉ[ suc k ] A  Γ ⊢ⁿᶠ[ suc k ] A
    lamⁿᶠ  :  {A B k}    Γ , A ⊢ⁿᶠ[ k ] B  Γ ⊢ⁿᶠ[ k ] A  B
    pairⁿᶠ :  {A B k l}  Γ ⊢ⁿᶠ[ k ] A  Γ ⊢ⁿᶠ[ l ] B  Γ ⊢ⁿᶠ[ k + l ] A  B
    unitⁿᶠ : Γ ⊢ⁿᶠ[ 0 ] 

  infix 3 _⊢ⁿᵉ[_]_
  data _⊢ⁿᵉ[_]_ (Γ : Cx Ty) :   Ty  Set where
    varⁿᵉ :  {A k}      A  Γ  Γ ⊢ⁿᵉ[ k ] A
    appⁿᵉ :  {A B k l}  Γ ⊢ⁿᵉ[ k ] A  B  Γ ⊢ⁿᶠ[ l ] A  Γ ⊢ⁿᵉ[ suc (k + l) ] B
    fstⁿᵉ :  {A B k}    Γ ⊢ⁿᵉ[ k ] A  B  Γ ⊢ⁿᵉ[ suc k ] A
    sndⁿᵉ :  {A B k}    Γ ⊢ⁿᵉ[ k ] A  B  Γ ⊢ⁿᵉ[ suc k ] B

mutual
  nf→tm :  {Γ A k}  Γ ⊢ⁿᶠ[ k ] A  Γ  A
  nf→tm (neⁿᶠ t)     = ne→tm t
  nf→tm (lamⁿᶠ t)    = lam (nf→tm t)
  nf→tm (pairⁿᶠ t u) = pair (nf→tm t) (nf→tm u)
  nf→tm unitⁿᶠ       = unit

  ne→tm :  {Γ A k}  Γ ⊢ⁿᵉ[ k ] A  Γ  A
  ne→tm (varⁿᵉ i)   = var i
  ne→tm (appⁿᵉ t u) = app (ne→tm t) (nf→tm u)
  ne→tm (fstⁿᵉ t)   = fst (ne→tm t)
  ne→tm (sndⁿᵉ t)   = snd (ne→tm t)

data NfNe⁼ {Γ A} (k : ) (t : Γ  A) : Set where
  nfⁿᶠⁿᵉ⁼ : (t′ : Γ ⊢ⁿᶠ[ k ] A)  {{_ : nf→tm t′  t}}  NfNe⁼ k t
  neⁿᶠⁿᵉ⁼ : (t′ : Γ ⊢ⁿᵉ[ k ] A)  {{_ : ne→tm t′  t}}  NfNe⁼ k t


mutual
  data Nf {Γ} :  {A}    Γ  A  Set where
    neⁿᶠ   :  {A k}     {t : Γ  A}               Ne (suc k) t  Nf (suc k) t
    lamⁿᶠ  :  {A B k}   {t : Γ , A  B}           Nf k t  Nf k (lam t)
    pairⁿᶠ :  {A B k l} {t : Γ  A} {u : Γ  B}  Nf k t  Nf l u  Nf (k + l) (pair t u)
    unitⁿᶠ : Nf 0 unit

  data Ne {Γ} :  {A}    Γ  A  Set where
    varⁿᵉ :  {A k}                                    (i : A  Γ)  Ne k (var i)
    appⁿᵉ :  {A B k l} {t : Γ  A  B} {u : Γ  A}  Ne k t  Nf l u  Ne (suc (k + l)) (app t u)
    fstⁿᵉ :  {A B k}   {t : Γ  A  B}               Ne k t  Ne (suc k) (fst t)
    sndⁿᵉ :  {A B k}   {t : Γ  A  B}               Ne k t  Ne (suc k) (snd t)

data NfNe {Γ A} (k : ) (t : Γ  A) : Set where
  nfⁿᶠⁿᵉ : Nf k t  NfNe k t
  neⁿᶠⁿᵉ : Ne k t  NfNe k t

-- mutual
--   expⁿᶠ : ∀ {Γ A k} {t : Γ ⊢ A} → Nf t → Σ (Γ ⊢ⁿᶠ A) (λ t′ → nf→tm t′ ≡ t)
--   expⁿᶠ (neⁿᶠ d)     with expⁿᵉ d
--   expⁿᶠ (neⁿᶠ d)     | t′ , refl = neⁿᶠ t′ , refl
--   expⁿᶠ (lamⁿᶠ d)    with expⁿᶠ d
--   expⁿᶠ (lamⁿᶠ d)    | t′ , refl = lamⁿᶠ t′ , refl
--   expⁿᶠ (pairⁿᶠ d e) with expⁿᶠ d | expⁿᶠ e
--   expⁿᶠ (pairⁿᶠ d e) | t′ , refl | u′ , refl = pairⁿᶠ t′ u′ , refl
--   expⁿᶠ unitⁿᶠ       = unitⁿᶠ , refl

--   expⁿᵉ : ∀ {Γ A k} {t : Γ ⊢ A} → Ne t → Σ (Γ ⊢ⁿᵉ A) (λ t′ → ne→tm t′ ≡ t)
--   expⁿᵉ (varⁿᵉ i)   = varⁿᵉ i , refl
--   expⁿᵉ (appⁿᵉ d e) with expⁿᵉ d | expⁿᶠ e
--   expⁿᵉ (appⁿᵉ d e) | t′ , refl | u′ , refl = appⁿᵉ t′ u′ , refl
--   expⁿᵉ (fstⁿᵉ d)   with expⁿᵉ d
--   expⁿᵉ (fstⁿᵉ d)   | t′ , refl = fstⁿᵉ t′ , refl
--   expⁿᵉ (sndⁿᵉ d)   with expⁿᵉ d
--   expⁿᵉ (sndⁿᵉ d)   | t′ , refl = sndⁿᵉ t′ , refl

-- expⁿᶠⁿᵉ : ∀ {Γ A k} {t : Γ ⊢ A} → NfNe t → NfNe⁼ t
-- expⁿᶠⁿᵉ (nfⁿᶠⁿᵉ d) with expⁿᶠ d
-- expⁿᶠⁿᵉ (nfⁿᶠⁿᵉ d) | t′ , refl = nfⁿᶠⁿᵉ⁼ t′
-- expⁿᶠⁿᵉ (neⁿᶠⁿᵉ d) with expⁿᵉ d
-- expⁿᶠⁿᵉ (neⁿᶠⁿᵉ d) | t′ , refl = neⁿᶠⁿᵉ⁼ t′