module Implicit.Language.Extension.Occur where

open import Implicit.Language.Base
open import Implicit.Language.Shift.All
open import Implicit.Language.Lookup.All
open import Implicit.Language.Occur.All
open import Implicit.Language.Extension.Base
open import Implicit.Language.Extension.InputOutput
open import Implicit.Language.Extension.ExSol
open import Implicit.Language.Extension.Properties

⊆/x-≢ : Γ  Δ w/v X
         Γ ∋^ k
         Δ ∋^ k
         X  k
⊆/x-≢ (ext-S^ ext) (S^ inΓ) (S^ inΔ) refl = ⊆/x-≢ ext inΓ inΔ refl
⊆/x-≢ (ext-S∙ ext) (S∙ inΓ) (S∙ inΔ) refl = ⊆/x-≢ ext inΓ inΔ refl
⊆/x-≢ (ext-S= ext regA) (S= inΓ) (S= inΔ) refl = ⊆/x-≢ ext inΓ inΔ refl

⊆-∋^-middle : Γ ∋^ k
             Δ ∋^ k
             Γ  Ω
             Ω  Δ
             Ω ∋^ k
⊆-∋^-middle Z Z (evar ext1) (evar ext2) = Z
⊆-∋^-middle (S∙ inΓ) (S∙ inΔ) (uvar ext1) (uvar ext2) = S∙ (⊆-∋^-middle inΓ inΔ ext1 ext2)
⊆-∋^-middle (S∙ inΓ) (S= inΔ) (uvar ext1) ()
⊆-∋^-middle (S∙ inΓ) (S^ inΔ) (uvar ext1) ()
⊆-∋^-middle (S= inΓ) (S∙ inΔ) (svar ext1 regA) ()
⊆-∋^-middle (S= inΓ) (S= inΔ) (svar ext1 regA) (svar ext2 regA₁) = S= (⊆-∋^-middle inΓ inΔ ext1 ext2)
⊆-∋^-middle (S= inΓ) (S^ inΔ) (svar ext1 regA) ()
⊆-∋^-middle (S^ inΓ) (S∙ inΔ) (evar ext1) ()
⊆-∋^-middle (S^ inΓ) (S∙ inΔ) (evar-sol ext1 regA) ()
⊆-∋^-middle (S^ inΓ) (S= inΔ) (evar ext1) (evar-sol ext2 regA) = S^ (⊆-∋^-middle inΓ inΔ ext1 ext2)
⊆-∋^-middle (S^ inΓ) (S= inΔ) (evar-sol ext1 regA) (svar ext2 regA₁) = S= (⊆-∋^-middle inΓ inΔ ext1 ext2)
⊆-∋^-middle (S^ inΓ) (S^ inΔ) (evar ext1) (evar ext2) = S^ (⊆-∋^-middle inΓ inΔ ext1 ext2)


^in-^out-¬ε : Γ  Δ w/t A
             Γ ∋^ k
             Δ ∋^ k
             k ¬ε A
^in-^out-¬ε (ext-int x) inΓ inΔ = ¬ε-int
^in-^out-¬ε (ext-var x) inΓ inΔ = ¬ε-var (⊆/x-≢ x inΓ inΔ)
^in-^out-¬ε (ext-arr ext ext₁) inΓ inΔ = let inΩ = ⊆-∋^-middle inΓ inΔ (⊆/-⊆ ext) (⊆/-⊆ ext₁)
                                         in ¬ε-arr (^in-^out-¬ε ext inΓ inΩ) (^in-^out-¬ε ext₁ inΩ inΔ)
^in-^out-¬ε (ext-∀ ext) inΓ inΔ = ¬ε-∀ (^in-^out-¬ε ext (S∙ inΓ) (S∙ inΔ))


^in-=out-ε : Γ  Δ w/t A
            Γ ∋^ k
            Δ ∋= k
            k ε A
^in-=out-ε (ext-int regΓ) inΓ inΔ = ⊥-elim (∋^-∋=-false inΓ inΔ)
^in-=out-ε (ext-var x) inΓ inΔ with ⊆/x-^in-=out-eq x inΓ inΔ
... | refl = ε-var
^in-=out-ε (ext-arr ext ext₁) inΓ inΔ with ⊆/-exsol ext inΓ
... | is-ex inΓ₁ = ε-arr-r (^in-^out-¬ε ext inΓ inΓ₁) (^in-=out-ε ext₁ inΓ₁ inΔ)
... | is-sol inΓ₁ = ε-arr-l (^in-=out-ε ext inΓ inΓ₁)
^in-=out-ε (ext-∀ ext) inΓ inΔ = ε-∀ (^in-=out-ε ext (S∙ inΓ) (S∙ inΔ))