module NCILL.Admit.Implication where

open import Data.List
open import Data.Empty

open import ListExtras
open import AssocProofs

open import NCILL.Types
open import NCILL.Ctx
open import NCILL.Sequent
open import NCILL.ProofUtils
open import NCILL.Admit.Action

-- IMPLICATION
------------------------------------------------------------------------

admit-impl-L-after :  Γ Ψ Φ Δ₁ Δ₂ A B C D 
  Action2
    Γ C
    Ψ A
    (Δ₁ ++ B  Φ ++ C  Δ₂) D
    (((Δ₁ ++ Ψ) ++ A  B  Φ) ++ Γ ++ Δ₂) D
admit-impl-L-after Γ Ψ Φ Δ₁ Δ₂ A B C D =
  action₂ (Δ₁ ++ B  Φ) obligation₁ λ e₁ e₂ 
    subst-Sqnt-Γ obligation₂
    (impl-L Δ₁ e₁
    (subst-Sqnt-Γ obligation₃ e₂))
  where
    obligation₁ :  Δ₁ ++ B  Φ ++ C  Δ₂  (Δ₁ ++ B  Φ) ++ C  Δ₂
    obligation₁ = xs++xs++xs≡[xs++xs]++xs Δ₁ (B  Φ) (C  Δ₂)

    obligation₂ : Δ₁ ++ Ψ ++ A  B  Φ ++ Γ ++ Δ₂  ((Δ₁ ++ Ψ) ++ A  B  Φ) ++ Γ ++ Δ₂
    obligation₂ = xs++xs++xs++xs≡[[xs++xs]++xs]++xs Δ₁ Ψ (A  B  Φ) (Γ ++ Δ₂)

    obligation₃ : (Δ₁ ++ B  Φ) ++ Γ ++ Δ₂  Δ₁ ++ B  Φ ++ Γ ++ Δ₂
    obligation₃ = [xs++xs]++xs≡xs++xs++xs Δ₁ (B  Φ) (Γ ++ Δ₂)

admit-impl-L-before :  Γ Ψ Δ₂ Δ₁ Ω₁ Ω₂ A B C D
   Ω₁ ++ Ψ  Δ₁ ++ C  Δ₂
   Action2
    Γ C
    Ψ A
    (Ω₁ ++ B  Ω₂) D
    (Δ₁ ++ Γ ++ Δ₂ ++ A  B  Ω₂) D
admit-impl-L-before  Γ Ψ Δ₂ Δ₁ Ω₁ Ω₂ A B C D eq with find-cons Ω₁ Δ₁ eq
admit-impl-L-before Γ Ψ Δ₂ Δ₁ Ω₁ Ω₂ A B C D _ | in-first Φ refl refl =
  action₂ Δ₁ obligation₁ λ e₁ e₂ 
    subst-Sqnt-Γ obligation₂
    (impl-L (Δ₁ ++ Γ ++ Φ) e₁
    (subst-Sqnt-Γ obligation₃ e₂))
  where
    obligation₁ : (Δ₁ ++ C  Φ) ++ B  Ω₂  Δ₁ ++ C  Φ ++ B  Ω₂
    obligation₁ = [xs++xs]++xs≡xs++xs++xs Δ₁ (C  Φ) (B  Ω₂)

    obligation₂ : (Δ₁ ++ Γ ++ Φ) ++ Ψ ++ A  B  Ω₂  Δ₁ ++ Γ ++ (Φ ++ Ψ) ++ A  B  Ω₂
    obligation₂ = [xs++xs++xs]++xs++xs≡xs++xs++[xs++xs]++xs Δ₁ Γ Φ Ψ (A  B  Ω₂)

    obligation₃ : Δ₁ ++ Γ ++ Φ ++ B  Ω₂  (Δ₁ ++ Γ ++ Φ) ++ B  Ω₂
    obligation₃ = xs++xs++xs++xs≡[xs++xs++xs]++xs Δ₁ Γ Φ (B  Ω₂)

admit-impl-L-before Γ Ψ Δ₂ Δ₁ Ω₁ Ω₂ A B C D _ | in-second Φ refl refl =
  action₁ Φ refl λ e₁ e₂ 
    subst-Sqnt-Γ obligation₁
    (impl-L Ω₁ e₁ e₂)
  where
    obligation₁ : Ω₁ ++ (Φ ++ Γ ++ Δ₂) ++ A  B  Ω₂  (Ω₁ ++ Φ) ++ Γ ++ Δ₂ ++ A  B  Ω₂
    obligation₁ = xs++[xs++xs++xs]++xs≡[xs++xs]++xs++xs++xs Ω₁ Φ Γ Δ₂ (A  B  Ω₂)

admit-impl-L :  Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ A B C D
   Ω₁ ++ Ψ ++ A  B  Ω₂  Δ₁ ++ C  Δ₂
   (A  B  C  )
   Action2
    Γ C
    Ψ A
    (Ω₁ ++ B  Ω₂) D
    (Δ₁ ++ Γ ++ Δ₂) D
admit-impl-L Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ A B C D eq _ with match-cons-2 Ω₁ Ψ Δ₁ eq
admit-impl-L Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ A B C D _ ineq | here refl eq refl with ineq eq
... | ()
admit-impl-L Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ A B C D _ _ | before Φ eq refl =
  admit-impl-L-before Γ Ψ Φ Δ₁ Ω₁ Ω₂ A B C D eq
admit-impl-L Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ A B C D _ _ | after Φ refl refl =
  admit-impl-L-after Γ Ψ Φ Ω₁ Δ₂ A B C D

-- REVERSE IMPLICATION
------------------------------------------------------------------------

admit-app-L-after :  (Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ : Ctx )  (D C A B : Ty)
   Ψ ++ Ω₂  Δ₁ ++ D  Δ₂
   Action2
    Γ D
    Ψ A
    (Ω₁ ++ B  Ω₂) C
    ((Ω₁ ++ A ⊸ʳ B  Δ₁) ++ Γ ++ Δ₂) C
admit-app-L-after  _ Ψ Δ₁ _ _ _ _ _ _ _ eq with find-cons Ψ Δ₁ eq
admit-app-L-after Γ Ψ Δ₁ _ Ω₁ Ω₂ D C A B eq | in-first Φ refl refl =
  action₁ Δ₁ refl λ e₁ e₂ 
    subst-Sqnt-Γ obligation₁ (impl-Lʳ Ω₁ e₁ e₂)
  where
    obligation₁ : Ω₁ ++ A ⊸ʳ B  (Δ₁ ++ Γ ++ Φ) ++ Ω₂  (Ω₁ ++ A ⊸ʳ B  Δ₁) ++ Γ ++ Φ ++ Ω₂
    obligation₁ = list-solve {n = 6}
      (bla :++ bla :++ (bla :++ bla :++ bla) :++ bla :≡ (bla :++ bla :++ bla) :++ bla :++ bla :++ bla)
      Ω₁ [ A ⊸ʳ B ] Δ₁ Γ Φ Ω₂
admit-app-L-after Γ Ψ Δ₁ Δ₂ Ω₁ _ D C A B eq | in-second Φ refl refl =
  action₂ (Ω₁ ++ B  Φ) obligation₁ λ e₁ e₂ 
    subst-Sqnt-Γ obligation₃ (impl-Lʳ Ω₁ e₁ (subst-Sqnt-Γ obligation₂ e₂))
  where
    obligation₁ : Ω₁ ++ B  Φ ++ D  Δ₂  (Ω₁ ++ B  Φ) ++ D  Δ₂
    obligation₁ = xs++xs++xs≡[xs++xs]++xs Ω₁ (B  Φ) (D  Δ₂)

    obligation₂ : (Ω₁ ++ B  Φ) ++ Γ ++ Δ₂  Ω₁ ++ B  Φ ++ Γ ++ Δ₂
    obligation₂ = [xs++xs]++xs++xs≡xs++xs++xs++xs Ω₁ (B  Φ) Γ Δ₂

    obligation₃ : Ω₁ ++ A ⊸ʳ B  Ψ ++ Φ ++ Γ ++ Δ₂  (Ω₁ ++ A ⊸ʳ B  Ψ ++ Φ) ++ Γ ++ Δ₂
    obligation₃ = xs++xs++xs++xs≡[xs++xs++xs]++xs Ω₁ (A ⊸ʳ B  Ψ) Φ (Γ ++ Δ₂)

admit-app-L-before : (Γ Ψ Ω Δ₁ Δ₂ : Ctx) (A B C D : Ty)
   Action2
    Γ A
    Ψ C
    ((Δ₁ ++ A  Ω) ++ D  Δ₂) B
    (Δ₁ ++ Γ ++ Ω ++ C ⊸ʳ D  Ψ ++ Δ₂) B
admit-app-L-before Γ Ψ Ω Δ₁ Δ₂ A B C D =
  action₂ Δ₁ obligation₁ λ e₁ e₂ 
    subst-Sqnt-Γ obligation₃
    (impl-Lʳ (Δ₁ ++ Γ ++ Ω) e₁
    (subst-Sqnt-Γ obligation₂ e₂))
  where
    obligation₁ : (Δ₁ ++ A  Ω) ++ D  Δ₂  Δ₁ ++ A  Ω ++ D  Δ₂
    obligation₁ = [xs++xs]++xs≡xs++xs++xs Δ₁ (A  Ω) (D  Δ₂)

    obligation₂ : Δ₁ ++ Γ ++ Ω ++ D  Δ₂  (Δ₁ ++ Γ ++ Ω) ++ D  Δ₂
    obligation₂ = xs++xs++xs++xs≡[xs++xs++xs]++xs Δ₁ Γ Ω (D  Δ₂)

    obligation₃ : (Δ₁ ++ Γ ++ Ω) ++ C ⊸ʳ D  Ψ ++ Δ₂  Δ₁ ++ Γ ++ Ω ++ C ⊸ʳ D  Ψ ++ Δ₂
    obligation₃ = [xs++xs++xs]++xs≡xs++xs++xs++xs Δ₁ Γ Ω (C ⊸ʳ D  Ψ ++ Δ₂)

admit-app-L : (Γ Ψ Δ₁ Δ₂ Ω₁ Ω₂ : Ctx)  (A B C D : Ty)
   Ω₁ ++ A ⊸ʳ B  Ψ ++ Ω₂  Δ₁ ++ D  Δ₂
   (A ⊸ʳ B  D  )
   Action2
    Γ D
    Ψ A
    (Ω₁ ++ B  Ω₂) C
    (Δ₁ ++ Γ ++ Δ₂) C
admit-app-L _ _ Δ₁ _ Ω₁ _ _ _ _ _ eq _  with match-cons Ω₁ Δ₁ eq
admit-app-L _ _ _ _ _ _ _ _ _ _ _ ineq | here _ eq _ with ineq eq
... | ()
admit-app-L Γ Ψ Δ₁ _ _ Ω₂ A B C D _ _  | before Φ refl refl =
  admit-app-L-before Γ Ψ Φ Δ₁ Ω₂ D C A B
admit-app-L Γ Ψ _ Δ₂ Ω₁ Ω₂ A B C D _ _  | after Φ eq refl =
  admit-app-L-after Γ Ψ Φ Δ₂ Ω₁ Ω₂ D C A B eq