{-# OPTIONS --safe #-}
module Data.Permutation.Normalised.Injective where
open import Prelude hiding (_↔_)
open import Data.List hiding ([]; _∷_)
open import Data.Nat.Properties renaming (discreteℕ to infix 4 _≟_)
open import Data.Permutation.Swap _≟_
open import Data.Permutation.NonNorm _≟_
open import Data.Nat using (_+_)
open import Data.Permutation.Normalised.Definition
open import Data.List.Properties
open import Data.Permutation.Normalised.Unnorm
open import Data.Nat.Compare
step-lemma : ∀ x y xs ys → (∀ n → xs ∘⟨ x , y ⟩ ⊙ n ≡ ys ∘⟨ x , y ⟩ ⊙ n) → ∀ n → xs ⊙ n ≡ ys ⊙ n
step-lemma x y xs ys p n with y ≟ n
... | no y≢n =
let h =
sym (cong (λ e → xs ⊙+ suc x ⊙ e) (swap-neq x (suc x + y) (suc x + n) (x≢sx+y x n) (y≢n ∘ +-inj (suc x)))
; ⊙+⊙ (suc x) _ xs)
; sym (⊙-alg-com x y xs (suc x + n) ; cong′ {A = ℕ} (λ e → xs ⊙+ suc x ⊙ e) (⊙-· x y (suc (x + n))))
; p (suc x + n)
; ⊙-alg-com x y ys (suc x + n) ; cong′ {A = ℕ} (λ e → ys ⊙+ suc x ⊙ e) (⊙-· x y (suc (x + n)))
; cong (λ e → ys ⊙+ suc x ⊙ e) (swap-neq x (suc x + y) (suc x + n) (x≢sx+y x n) (y≢n ∘ +-inj (suc x)))
; ⊙+⊙ (suc x) _ ys
in +-inj (suc x) h
... | yes y≡n =
let h = sym (⊙-alg-com x y xs x ; cong (λ e → xs ⊙+ suc x ⊙ e) (⊙-· x y x ; swap-lhs x _) ; ⊙+⊙ (suc x) y xs)
; p x
; ⊙-alg-com x y ys x ; cong (λ e → ys ⊙+ suc x ⊙ e) (⊙-· x y x ; swap-lhs x _) ; ⊙+⊙ (suc x) y ys
in cong (xs ⊙_) (sym y≡n) ; +-inj (suc x) h ; cong (ys ⊙_) y≡n
⊙-inj : ∀ xs n m → xs ⊙ n ≡ xs ⊙ m → n ≡ m
⊙-inj xs n m p = perm-inj [ xs ]↑ n m (sym (⊙↑-hom xs n) ; p ; ⊙↑-hom xs m)
inj-⊙-lemma : ∀ x xₜ yₜ xs ys
→ (∀ n → xs ∘⟨ x , xₜ ⟩ ⊙ n ≡ ys ∘⟨ x , yₜ ⟩ ⊙ n)
→ xₜ ≢ yₜ
→ xs ⊙ xₜ ≡ ys ⊙ yₜ
→ ∀ n
→ xs ⊙ n ≡ ys ⊙ n
inj-⊙-lemma x xₜ yₜ xs ys p xₜ≢yₜ xye n with n ≟ xₜ | n ≟ yₜ
... | yes n≡xₜ | yes n≡yₜ = ⊥-elim (xₜ≢yₜ (sym n≡xₜ ; n≡yₜ))
... | no n≢xₜ | yes n≡yₜ =
⊥-elim (x≢sx+y x (xs ⊙ n) (sym (sym (⊙-lhs x xₜ xs n (n≢xₜ ∘ sym)) ; p (suc x + n) ; cong (λ e → ys ∘⟨ x , yₜ ⟩ ⊙ suc x + e) n≡yₜ ; ⊙-rhs x yₜ ys)))
... | yes n≡xₜ | no n≢yₜ =
⊥-elim (x≢sx+y x (ys ⊙ n)
( sym (⊙-rhs x xₜ xs)
; cong (λ e → xs ∘⟨ x , xₜ ⟩ ⊙ suc x + e) (sym n≡xₜ)
; p (suc x + n)
; ⊙-lhs x yₜ ys n (n≢yₜ ∘ sym)
))
... | no n≢xₜ | no n≢yₜ =
+-inj (suc x) (sym (⊙-lhs x xₜ xs n (n≢xₜ ∘ sym)) ; p (suc x + n) ; ⊙-lhs x yₜ ys n (n≢yₜ ∘ sym))
inj-⊙ : ∀ xs ys → (∀ n → xs ⊙ n ≡ ys ⊙ n) → xs ≡ ys
inj-⊙ ⟨⟩ ⟨⟩ _ = refl
inj-⊙ ⟨⟩ (ys ∘⟨ x , y ⟩) p = ⊥-elim (⊙-lhs-neq x y ys (sym (p x)))
inj-⊙ (xs ∘⟨ x , y ⟩) ⟨⟩ p = ⊥-elim (⊙-lhs-neq x y xs (p x))
inj-⊙ (xs ∘⟨ xₛ , xₜ ⟩) (ys ∘⟨ yₛ , yₜ ⟩) p with xₛ ≟ yₛ | xₜ ≟ yₜ
... | yes xₛ≡yₛ | yes xₜ≡yₜ = cong₂ _∘⟨_⟩ (inj-⊙ xs ys λ n → step-lemma xₛ xₜ xs ys (_; cong₂ (λ e₁ e₂ → ys ∘⟨ e₁ , e₂ ⟩ ⊙ _) (sym xₛ≡yₛ) (sym xₜ≡yₜ) ∘ p) n ) (cong₂ _,_ xₛ≡yₛ xₜ≡yₜ)
... | yes xₛ≡yₛ | no xₜ≢yₜ =
let h = +-inj (suc xₛ) $ sym (⊙-alg-com xₛ xₜ xs xₛ ; cong (λ e → xs ⊙+ suc xₛ ⊙ e) (⊙-· xₛ xₜ xₛ ; swap-lhs xₛ _) ; ⊙+⊙ (suc xₛ) xₜ xs)
; p xₛ
; cong (ys ∘⟨ yₛ , yₜ ⟩ ⊙_) xₛ≡yₛ
; ⊙-alg-com yₛ yₜ ys yₛ ; cong (λ e → ys ⊙+ suc yₛ ⊙ e) (⊙-· yₛ yₜ yₛ ; swap-lhs yₛ _) ; ⊙+⊙ (suc yₛ) yₜ ys
; cong suc (cong (_+ (ys ⊙ yₜ)) (sym xₛ≡yₛ))
h′ = inj-⊙ xs ys (inj-⊙-lemma xₛ xₜ yₜ xs ys ( λ n → p n ; cong (λ e → ys ∘⟨ e , yₜ ⟩ ⊙ n) (sym xₛ≡yₛ) ) xₜ≢yₜ h )
h″ = ⊙-inj xs xₜ yₜ (h ; cong (_⊙ yₜ) (sym h′))
in ⊥-elim (xₜ≢yₜ h″)
... | no xₛ≢yₛ | _ with compare xₛ yₛ | comparing xₛ yₛ
... | equal | xₛ≡yₛ = ⊥-elim (xₛ≢yₛ xₛ≡yₛ)
... | less k | xₛ<yₛ =
⊥-elim (⊙-lhs-neq xₛ xₜ xs (p xₛ ; cong (λ e → ys ∘⟨ e , yₜ ⟩ ⊙ xₛ) (sym xₛ<yₛ) ; ⊙-lt (ys ∘⟨ k , yₜ ⟩) xₛ))
... | greater k | yₛ<xₛ =
⊥-elim (⊙-lhs-neq yₛ yₜ ys (sym (p yₛ) ; cong (λ e → xs ∘⟨ e , xₜ ⟩ ⊙ yₛ) (sym yₛ<xₛ) ; ⊙-lt (xs ∘⟨ k , xₜ ⟩) yₛ))