module MLTT.Uniqueness where

open import Prelude
open import WSLN

open import MLTT.Syntax
open import MLTT.Judgement
open import MLTT.Cofinite
open import MLTT.Ok
open import MLTT.WellScoped
open import MLTT.Weakening
open import MLTT.Substitution
open import MLTT.Admissible
open import MLTT.ExistsFresh

----------------------------------------------------------------------
-- Types of terms are unique up to conversion and have a unique level
----------------------------------------------------------------------
svVr :
 {l l' : Lvl}
 {ฮ“ : Cx}
 {A A' : Ty}
 {x x' : ๐”ธ}
 (_ : Ok ฮ“)
 (_ : (x , A , l) isIn ฮ“)
 (_ : (x' , A' , l') isIn ฮ“)
 (_ : x โ‰ก x')
 โ†’ -------------------------
 (l โ‰ก l') โˆง (A โ‰ก A')

svVr _ isInNew isInNew _ = refl , refl
svVr (okโจŸ _ q _) isInNew (isInOld p') refl =
  ร˜elim (โˆ‰โ†’ยฌโˆˆ q (isInโ†’dom p'))
svVr (okโจŸ _ q _) (isInOld p) isInNew refl =
  ร˜elim (โˆ‰โ†’ยฌโˆˆ q (isInโ†’dom p))
svVr (okโจŸ _ _ q) (isInOld p) (isInOld p') e = svVr q p p' e

svTy :
  {l l' : Lvl}
  {ฮ“ : Cx}
  {A A' : Ty}
  {a : Tm}
  (_ : ฮ“ โŠข a โˆถ A โฆ‚ l)
  (_ : ฮ“ โŠข a โˆถ A' โฆ‚ l')
  โ†’ ---------------------------
  (l โ‰ก l') โˆง (ฮ“ โŠข A ๏ผ A' โฆ‚ l)

svTy (โŠขconv qโ‚€ qโ‚) q' with (refl , q) โ† svTy qโ‚€ q' =
  (refl , Trans (Symm qโ‚) q)

svTy q (โŠขconv qโ‚€' qโ‚') with (refl , q') โ† svTy q qโ‚€' =
  (refl , Trans q' qโ‚')

svTy (โŠข๐ฏ qโ‚€ qโ‚) (โŠข๐ฏ _ qโ‚')
  with (refl , refl) โ† svVr qโ‚€ qโ‚ qโ‚' refl =
  (refl , Refl (okโ†’ty qโ‚€ qโ‚))

svTy (โŠข๐” q) (โŠข๐” _) = (refl , Refl (โŠข๐” q))

svTy (โŠข๐šท _ qโ‚€ _) (โŠข๐šท _ _ _) = refl , (Refl (โŠข๐” (โŠขok qโ‚€)))

svTy (โŠข๐›Œ{B = B} S qโ‚€ qโ‚ _) (โŠข๐›Œ{B = B'} S' qโ‚€' qโ‚' _)
  with (refl , _ ) โ† svTy qโ‚ qโ‚'
  | (x , x#S โˆ‰โˆช x#S' โˆ‰โˆช x#) โ† fresh (S , S' , B , B')
  with (refl , r) โ† svTy (qโ‚€ x x#S) (qโ‚€' x x#S') =
  refl , (๐šทCongโป (Refl qโ‚) r x#)

svTy (โŠขโˆ™{B = B} S _ qโ‚ qโ‚‚ _) (โŠขโˆ™ S' _ qโ‚' qโ‚‚' _)
  with (refl , _) โ† svTy qโ‚ qโ‚'
  | (x , x#S โˆ‰โˆช x#S' โˆ‰โˆช x#) โ† fresh (S , S' , B)
  with (refl , _) โ† svTy (qโ‚‚ x x#S) (qโ‚‚' x x#S') =
  (refl , Refl (concTy B x (qโ‚‚ x x#S) qโ‚ x#))

svTy (โŠข๐ˆ๐ q _ _) (โŠข๐ˆ๐ q' _ _)
  with (refl , _) โ† svTy q q' =
  (refl , Refl (โŠข๐” (โŠขok q)))

svTy (โŠข๐ซ๐ž๐Ÿ๐ฅ q _) (โŠข๐ซ๐ž๐Ÿ๐ฅ q' _)
  with (refl , r) โ† svTy q q' =
  (refl , ๐ˆ๐Cong r (Refl q) (Refl q))

svTy{ฮ“ = ฮ“} (โŠข๐‰{l}{A = A}{C}{a}{b}{e = e} S qโ‚€ qโ‚ qโ‚‚ qโ‚ƒ qโ‚„ hโ‚€ hโ‚)
     (โŠข๐‰ _ _ qโ‚' _ qโ‚ƒ' _ _ _)
  with (refl , _) โ† svTy qโ‚ qโ‚'
  | (refl , _) โ† svTy qโ‚ƒ qโ‚ƒ'
  | (y , y#S โˆ‰โˆช y#C) โ† fresh (S , C)
  with (x , x#y โˆ‰โˆช x#S) โ† fresh (y , S) =
  (refl , Refl (concTyยฒ C x y
    (qโ‚€ x y (##:: y#S (##:: (x#y โˆ‰โˆช x#S) ##โ—‡)))
    qโ‚‚
    q
    x#C
    y#C))
  where
  x#ฮ“ : x # ฮ“
  x#ฮ“ = ฯ€โ‚ ([]โปยน (โŠขok (hโ‚ x x#S)))
  x#A : x # A
  x#A = โІโˆ‰ (โŠขsupp hโ‚€ โˆ˜ โˆˆโˆชโ‚) x#ฮ“
  x#a : x # a
  x#a = โІโˆ‰ (โŠขsupp qโ‚ โˆ˜ โˆˆโˆชโ‚) x#ฮ“
  x#C : x # C
  x#C = โІโˆ‰ (โŠขsupp qโ‚ƒ โˆ˜ โˆˆโˆชโ‚‚ โˆ˜ []ยฒsupp C a (๐ซ๐ž๐Ÿ๐ฅ a)) x#ฮ“

  q : ฮ“ โŠข e โˆถ (x := b) * ๐ˆ๐ A a (๐ฏ x) โฆ‚ l
  q rewrite ssbFresh x b A x#A
    | ssbFresh x b a x#a
    | updateEq{id}{b} x = qโ‚„

svTy (โŠข๐๐š๐ญ q) (โŠข๐๐š๐ญ _) = (refl , Refl (โŠข๐” q))

svTy (โŠข๐ณ๐ž๐ซ๐จ q) (โŠข๐ณ๐ž๐ซ๐จ _) = (refl , Refl (โŠข๐๐š๐ญ q))

svTy (โŠข๐ฌ๐ฎ๐œ๐œ q) (โŠข๐ฌ๐ฎ๐œ๐œ _) = (refl , Refl (โŠข๐๐š๐ญ (โŠขok q)))

svTy (โŠข๐ง๐ซ๐ž๐œ{C = C} S qโ‚€ _ qโ‚‚ h) (โŠข๐ง๐ซ๐ž๐œ _ qโ‚€' _ _ _)
  with (refl , _) โ† svTy qโ‚€ qโ‚€'
  | (x , x#S โˆ‰โˆช x#) โ† fresh (S , C) =
  (refl , Refl (concTy C x (h x x#S) qโ‚‚ x#))