{-# OPTIONS --safe #-}
module Data.Permutation.Normalised.Unnorm 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
unflatten-alg : ℕ → ℕ → (ℕ → Swaps) → ℕ → Swaps
unflatten-alg x y k n = k (suc n + x) ∘⟨ n + x , suc (n + x + y) ⟩
unflat : Diffs → ℕ → Swaps
unflat = foldr (uncurry unflatten-alg) (const ⟨⟩)
[_]↑ : Diffs → Swaps
[ xs ]↑ = unflat xs 0
swap-unf-alg : ℕ → ℕ → (ℕ → ℕ → ℕ) → ℕ → ℕ → ℕ
swap-unf-alg x y k m n = k (suc m + x) (m + x ↔ suc (m + x + y) · n)
open import Path.Reasoning
swap-shift : ∀ m n xs → xs ⊙+ m ⊙ n ≡ foldr (uncurry swap-unf-alg) (const id) xs m n
swap-shift m n ⟨⟩ = refl
swap-shift m n (xs ∘⟨ x , y ⟩) =
⊙-alg (m + x) y (xs ⊙_) n
≡⟨ ⊙-alg-com (m + x) y xs n ⟩
(xs ⊙+ suc m + x ⊙ m + x ↔ y ⊙ n)
≡⟨ cong (xs ⊙+ suc m + x ⊙_) (⊙-· (m + x) y n) ⟩
xs ⊙+ suc m + x ⊙ m + x ↔ suc m + x + y · n
≡⟨ swap-shift (suc m + x) _ xs ⟩
swap-unf-alg x y (foldr (uncurry swap-unf-alg) (const id) xs) m n ∎
⊙↑-hom : ∀ xs n → xs ⊙ n ≡ [ xs ]↑ · n
⊙↑-hom xs n =
xs ⊙ n
≡˘⟨ cong (_⊙ n) (shift-0 xs) ⟩
xs ⊙+ 0 ⊙ n
≡⟨ swap-shift 0 n xs ⟩
foldr (uncurry swap-unf-alg) (const id) xs 0 n
≡˘⟨ cong′ {A = ℕ → ℕ → ℕ} (λ e → e 0 n) (foldr-fusion (λ xs m n → foldl-by-r (flip (uncurry _↔_·_)) n (xs m)) (const ⟨⟩) (λ _ _ → refl) xs) ⟩
foldl-by-r (flip (uncurry _↔_·_)) n [ xs ]↑
≡˘⟨ foldl-is-foldr (flip (uncurry _↔_·_)) n [ xs ]↑ ⟩
[ xs ]↑ · n ∎