{-# OPTIONS --cubical --safe --prop #-}

open import Algebra
open import Prelude
open import Relation.Binary.Equivalence.PropTruncated

module Algebra.Construct.Cayley.Propositional {a} {𝑆 : Type a} (mon : Monoid 𝑆) where

open Monoid mon

record π’ž : Type a where
  constructor cayley
  infixr 7 _⇓_
  field
    _⇓_ : 𝑆 β†’ 𝑆
    small : βˆ€ x β†’ _⇓_ Ξ΅ βˆ™ x ≐ _⇓_ x
open π’ž public

⟦_β‡“βŸ§ : π’ž β†’ 𝑆
⟦ x β‡“βŸ§ = x ⇓ Ξ΅

⟦_β‡‘βŸ§ : 𝑆 β†’ π’ž
⟦ x β‡‘βŸ§ ⇓ y = x βˆ™ y
⟦ x β‡‘βŸ§ .small y = ∣ cong (_βˆ™ y) (βˆ™Ξ΅ x) ∣

β“” : π’ž
β“” ⇓ x = x
β“” .small x = ∣ Ξ΅βˆ™ x ∣

module _ where
  open Reasoning
  _βŠ™_ : π’ž β†’ π’ž β†’ π’ž
  (x βŠ™ y) ⇓ z = x ⇓ y ⇓ z
  (x βŠ™ y) .small z =
    x ⇓ y ⇓ Ξ΅ βˆ™ z       β‰Λ˜βŸ¨ βˆ™cong (_βˆ™ z) (x .small (y ⇓ Ξ΅)) ⟩
    x ⇓ Ξ΅ βˆ™ y ⇓ Ξ΅ βˆ™ z   β‰‘βŸ¨ assoc (x ⇓ Ξ΅) (y ⇓ Ξ΅) z ⟩
    x ⇓ Ξ΅ βˆ™ (y ⇓ Ξ΅ βˆ™ z) β‰βŸ¨ βˆ™cong (x ⇓ Ξ΅ βˆ™_) (y .small z)  ⟩
    x ⇓ Ξ΅ βˆ™ y ⇓ z       β‰βŸ¨ x .small (y ⇓ z) ⟩
    x ⇓ y ⇓ z ∎

βŠ™-assoc : Associative _βŠ™_
βŠ™-assoc x y z = refl

β“”βŠ™ : βˆ€ x β†’ β“” βŠ™ x ≑ x
β“”βŠ™ x = refl

βŠ™β“” : βˆ€ x β†’ x βŠ™ β“” ≑ x
βŠ™β“” x = refl

cayleyMonoid : Monoid π’ž
Monoid._βˆ™_ cayleyMonoid = _βŠ™_
Monoid.Ξ΅ cayleyMonoid = β“”
Monoid.assoc cayleyMonoid = βŠ™-assoc
Monoid.Ξ΅βˆ™ cayleyMonoid = β“”βŠ™
Monoid.βˆ™Ξ΅ cayleyMonoid = βŠ™β“”

open import Data.Sigma.Properties
open import Relation.Nullary.Stable

π’žβ‰‘ : {x y : π’ž} β†’ (βˆ€ z β†’ x ⇓ z ≑ y ⇓ z) β†’ x ≑ y
π’žβ‰‘ { f } { cayley g q } f≑g =
  subst
    (Ξ» (gβ€² : 𝑆 β†’ 𝑆) β†’ (qβ€² : βˆ€ x β†’ gβ€² Ξ΅ βˆ™ x ≐ gβ€² x) β†’ f ≑ cayley gβ€² qβ€²)
    (funExt f≑g)
    (Ξ» _ β†’ refl)
    q

βˆ™-homo : βˆ€ x y β†’ ⟦ x βˆ™ y β‡‘βŸ§ ≑ ⟦ x β‡‘βŸ§ βŠ™ ⟦ y β‡‘βŸ§
βˆ™-homo x y = π’žβ‰‘ (assoc x y)

Ξ΅-homo : ⟦ Ξ΅ β‡‘βŸ§ ≑ β“”
Ξ΅-homo = π’žβ‰‘ Ξ΅βˆ™

homo-to : MonoidHomomorphism mon ⟢ cayleyMonoid
MonoidHomomorphism_⟢_.f homo-to = ⟦_β‡‘βŸ§
MonoidHomomorphism_⟢_.βˆ™-homo homo-to = βˆ™-homo
MonoidHomomorphism_⟢_.Ρ-homo homo-to = Ρ-homo

β“”-homo : ⟦ β“” β‡“βŸ§ ≑ Ξ΅
β“”-homo = refl

module _ (sIsStable : βˆ€ {x y : 𝑆} β†’ Stable (x ≑ y)) where
  βŠ™-homo : βˆ€ x y β†’ ⟦ x βŠ™ y β‡“βŸ§ ≑ ⟦ x β‡“βŸ§ βˆ™ ⟦ y β‡“βŸ§
  βŠ™-homo x y = sym (unsquash sIsStable (x .small ⟦ y β‡“βŸ§))

  π’ž-iso : π’ž ⇔ 𝑆
  fun π’ž-iso = ⟦_β‡“βŸ§
  inv π’ž-iso = ⟦_β‡‘βŸ§
  rightInv π’ž-iso = βˆ™Ξ΅
  leftInv  π’ž-iso x = π’žβ‰‘ Ξ» y β†’ unsquash sIsStable (x .small y)

  homo-from : MonoidHomomorphism cayleyMonoid ⟢ mon
  MonoidHomomorphism_⟢_.f homo-from = ⟦_β‡“βŸ§
  MonoidHomomorphism_⟢_.βˆ™-homo homo-from = βŠ™-homo
  MonoidHomomorphism_⟢_.Ξ΅-homo homo-from = β“”-homo