{-# 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