{-# OPTIONS --without-K --rewriting --overlapping-instances --instance-search-depth=3 #-}

open import lib.Basics
open import lib.FTID
open import lib.types.Sigma
open import lib.types.Pi
open import lib.types.Paths
open import 2Semigroup

module 2SGrpMap where

open WkSGrp {{...}}
open WkSGrpNatIso

module _ {i j k l} {G₁ : Type i} {G₂ : Type j} {G₃ : Type k} {G₄ : Type l}
  {{η₁ : WkSGrp G₁}} {{η₂ : WkSGrp G₂}} {{η₃ : WkSGrp G₃}} {{η₄ : WkSGrp G₄}} where

  assoc-wksgrphom :
    (μ₁ : WkSGrpWkHom {{η₃}} {{η₄}}) (μ₂ : WkSGrpWkHom {{η₂}} {{η₃}}) (μ₃ : WkSGrpWkHom {{η₁}} {{η₂}})
     WkSGrpNatIso (μ₁ ∘2Mw μ₂ ∘2Mw μ₃) ((μ₁ ∘2Mw μ₂) ∘2Mw μ₃)
  θ (assoc-wksgrphom μ₁ μ₂ μ₃) x = idp
  θ-comp (assoc-wksgrphom μ₁ μ₂ μ₃) x y = =ₛ-out $
    (map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) 
    ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y))) ◃∙
    ap  v  map-wk μ₁ (map-wk μ₂ v)) (map-comp-wk μ₃ x y) ◃∎
      =ₛ₁⟨ 1 & 1 & ap-∘ (map-wk μ₁) (map-wk μ₂) (map-comp-wk μ₃ x y) 
    (map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) 
    ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y))) ◃∙
    ap (map-wk μ₁) (ap (map-wk μ₂) (map-comp-wk μ₃ x y)) ◃∎
      =ₑ⟨ 0 & 1 &
        (map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) ◃∙
        ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y)) ◃∎) % =ₛ-in idp 
    map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) ◃∙
    ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y)) ◃∙
    ap (map-wk μ₁) (ap (map-wk μ₂) (map-comp-wk μ₃ x y)) ◃∎
      =ₛ₁⟨ 1 & 2 & ∙-ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y)) _ 
    map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) ◃∙
    ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y) 
      ap (map-wk μ₂) (map-comp-wk μ₃ x y)) ◃∎
      =ₛ⟨ =ₛ-in (! (∙-unit-r (map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) 
             ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y) 
             ap (map-wk μ₂) (map-comp-wk μ₃ x y))))) 
    (map-comp-wk μ₁ (map-wk μ₂ (map-wk μ₃ x)) (map-wk μ₂ (map-wk μ₃ y)) 
    ap (map-wk μ₁) (map-comp-wk μ₂ (map-wk μ₃ x) (map-wk μ₃ y) 
    ap (map-wk μ₂) (map-comp-wk μ₃ x y))) ◃∙
    idp ◃∎ ∎ₛ

module _ {i j} {G₁ : Type i} {G₂ : Type j} {{η₁ : WkSGrp G₁}} {{η₂ : WkSGrp G₂}} where

   : {μ₁ μ₂ : WkSGrpWkHom {{η₁}} {{η₂}}} (γ : WkSGrpNatIso μ₁ μ₂)  WkSGrpNatIso μ₂ μ₁
  θ ( γ) x = ! (θ γ x)
  θ-comp ( γ) x y = aux {p₁ = θ γ x} (θ-comp γ x y)
    where
      aux : {x₁ x₂ x₃ x₄ x₅ x₆ : G₂} {p₁ : x₁ == x₂} {p₂ : x₃ == x₄}
        {p₃ : mu x₁ x₃ == x₅} {p₄ : x₅ == x₆} {p₀ : mu x₂ x₄ == x₆}
         p₀ == ! (ap2 mu p₁ p₂)  p₃  p₄
         p₃ == ! (ap2 mu (! p₁) (! p₂))  p₀  ! p₄
      aux {p₁ = idp} {p₂ = idp} {p₃ = idp} {p₄ = idp} idp = idp

  unit-wksgrphom-l : (μ : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso μ (idf2Mw {{η₂}} ∘2Mw μ)
  θ (unit-wksgrphom-l μ) x = idp
  θ-comp (unit-wksgrphom-l μ) x y = ap-idf (map-comp-wk μ x y)  ! (∙-unit-r (map-comp-wk μ x y))

  unit-wksgrphom-r : (μ : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso μ (μ ∘2Mw idf2Mw {{η₁}})
  θ (unit-wksgrphom-r μ) x = idp
  θ-comp (unit-wksgrphom-r μ) x y = idp

  unit-wksgrphom : (μ : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso (idf2Mw {{η₂}} ∘2Mw μ) μ
  unit-wksgrphom μ =  (unit-wksgrphom-l μ)

  module _ {μ : WkSGrpWkHom {{η₁}} {{η₂}}} where

    natiso-contr-aux :
      is-contr (Σ (Σ (G₁  G₂)  f  map-wk μ  f))
         (f , H)  Σ (((x , y) : G₁ × G₁)  mu (f x) (f y) == f (mu x y))
           c  ((x , y) : G₁ × G₁) 
            c (x , y) == ! (ap2 mu (H x) (H y))  uncurry (map-comp-wk μ) (x , y)  H (mu x y))))
    natiso-contr-aux = equiv-preserves-level (
      (Σ-contr-red
        {P = λ (f , H)  Σ (((x , y) : G₁ × G₁)  mu (f x) (f y) == f (mu x y))
           c  ((x , y) : G₁ × G₁) 
            c (x , y) == ! (ap2 mu (H x) (H y))  uncurry (map-comp-wk μ) (x , y)  H (mu x y))}
        (funhom-contr {f = map-wk μ}))⁻¹ )
      {{equiv-preserves-level
        ((Σ-emap-r  c  Π-emap-r  (x , y)  post∙-equiv (! (∙-unit-r (map-comp-wk μ x y)))) ∘e app=-equiv)))
        {{pathto-is-contr (uncurry (map-comp-wk μ))}}}}

    abstract
      natiso-contr : is-contr (Σ (WkSGrpWkHom {{η₁}} {{η₂}})  ν  WkSGrpNatIso μ ν))
      natiso-contr = equiv-preserves-level aux {{natiso-contr-aux}}
        where
          aux :
            Σ (Σ (G₁  G₂)  f  map-wk μ  f))
               (f , H)  Σ (((x , y) : G₁ × G₁)  mu (f x) (f y) == f (mu x y))
                 c  ((x , y) : G₁ × G₁) 
                  c (x , y) == ! (ap2 mu (H x) (H y))  uncurry (map-comp-wk μ) (x , y)  H (mu x y)))
            
            Σ (WkSGrpWkHom {{η₁}} {{η₂}})  ν  WkSGrpNatIso μ ν)
          aux =
            equiv
               ((f , H) , (q , c))  (wksgrphom f (curry q)) , (cohgrpnatiso H  x y  c (x , y))))
               (ν , ρ)  ((map-wk ν) , (θ ρ)) , ((λ (x , y)  map-comp-wk ν x y) ,  (x , y)  θ-comp ρ x y)))
               b  idp)
              λ a  idp

    natiso-ind :  {k} (P : (ν : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso μ ν   Type k)
       P μ (natiso-id μ)  (ν : WkSGrpWkHom {{η₁}} {{η₂}}) (p : WkSGrpNatIso μ ν)  P ν p
    natiso-ind P r ν p = ID-ind-map P natiso-contr r {ν} p

    natiso-ind-β :  {k} (P : (ν : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso μ ν   Type k)
       (r : P μ (natiso-id μ))  natiso-ind P r μ (natiso-id μ) == r
    natiso-ind-β P = ID-ind-map-β P natiso-contr 

    natiso-to-== : {ν : WkSGrpWkHom {{η₁}} {{η₂}}}  WkSGrpNatIso μ ν  μ == ν
    natiso-to-== {ν} = natiso-ind  δ _  μ == δ) idp ν

  -- equational reasoning for nat isos.

  infixr 10 _=⟦_⟧_
  infix  15 _∎ₙ

  _=⟦_⟧_ : (μ₁ : WkSGrpWkHom {{η₁}} {{η₂}}) {μ₂ μ₃ : _}
     WkSGrpNatIso μ₁ μ₂  WkSGrpNatIso μ₂ μ₃  WkSGrpNatIso μ₁ μ₃
  _=⟦_⟧_ μ₁ {μ₂} {μ₃} τ = natiso-ind  ν τ  WkSGrpNatIso ν μ₃  WkSGrpNatIso μ₁ μ₃)  x  x) μ₂ τ

  _∎ₙ : (μ : WkSGrpWkHom {{η₁}} {{η₂}})  WkSGrpNatIso μ μ
  μ ∎ₙ = natiso-id μ

module _ {i j k} {G₁ : Type i} {G₂ : Type j} {{η₁ : WkSGrp G₁}} {{η₂ : WkSGrp G₂}}
  {μ : WkSGrpWkHom {{η₁}} {{η₂}}} {G₃ : Type k} {{η₃ : WkSGrp G₃}} where

  natiso-whisk-r : {ν₁ ν₂ : WkSGrpWkHom {{η₂}} {{η₃}}} (τ : WkSGrpNatIso ν₁ ν₂)
     WkSGrpNatIso (ν₁ ∘2Mw μ) (ν₂ ∘2Mw μ)
  θ (natiso-whisk-r {ν₁} {ν₂} τ) x = θ τ (map-wk μ x)
  θ-comp (natiso-whisk-r {ν₁} {ν₂} τ) x y =
    natiso-ind
       ν τ 
        map-comp-wk ν (map-wk μ x) (map-wk μ y) 
        ap (map-wk ν) (map-comp-wk μ x y)
          ==
        ! (ap2 mu (θ τ (map-wk μ x)) (θ τ (map-wk μ y))) 
        (map-comp-wk ν₁ (map-wk μ x) (map-wk μ y) 
        ap (map-wk ν₁) (map-comp-wk μ x y)) 
        θ τ (map-wk μ (mu x y)))
      (! (∙-unit-r _)) ν₂ τ

module _ {i j k} {G₁ : Type i} {G₂ : Type j} {{η₁ : WkSGrp G₁}} {{η₂ : WkSGrp G₂}}
  {G₃ : Type k} {{η₃ : WkSGrp G₃}} {μ : WkSGrpWkHom {{η₂}} {{η₃}}} where

  natiso-whisk-l : {ν₁ ν₂ : WkSGrpWkHom {{η₁}} {{η₂}}} (τ : WkSGrpNatIso ν₁ ν₂)
     WkSGrpNatIso (μ ∘2Mw ν₁) (μ ∘2Mw ν₂)
  θ (natiso-whisk-l {ν₁} {ν₂} τ) x = ap (map-wk μ) (θ τ x)
  θ-comp (natiso-whisk-l {ν₁} {ν₂} τ) x y =
    natiso-ind
       ν τ 
        map-comp-wk μ (map-wk ν x) (map-wk ν y) 
        ap (map-wk μ) (map-comp-wk ν x y)
          ==
        ! (ap2 mu (ap (map-wk μ) (θ τ x)) (ap (map-wk μ) (θ τ y))) 
        (map-comp-wk μ (map-wk ν₁ x) (map-wk ν₁ y) 
        ap (map-wk μ) (map-comp-wk ν₁ x y)) 
        ap (map-wk μ) (θ τ (mu x y)))
      (! (∙-unit-r _)) ν₂ τ

-- composite of triangles
module _ {i j k l} {G₁ : Type i} {G₂ : Type j} {G₃ : Type k} {G₄ : Type l}
  {{η₁ : WkSGrp G₁}} {{η₂ : WkSGrp G₂}} {{η₃ : WkSGrp G₃}} {{η₄ : WkSGrp G₄}} where

  natiso-tri-∘ : {μ₁ : WkSGrpWkHom {{η₁}} {{η₂}}} {μ₂ : WkSGrpWkHom {{η₁}} {{η₃}}} {μ₃ : WkSGrpWkHom {{η₁}} {{η₄}}}
    {ω₁ : WkSGrpWkHom {{η₂}} {{η₃}}} {ω₂ : WkSGrpWkHom {{η₃}} {{η₄}}}
     WkSGrpNatIso (ω₁ ∘2Mw μ₁) μ₂  WkSGrpNatIso (ω₂ ∘2Mw μ₂) μ₃  WkSGrpNatIso (ω₂ ∘2Mw ω₁ ∘2Mw μ₁) μ₃
  natiso-tri-∘ {μ₁} {μ₂} {μ₃} {ω₁} {ω₂} τ = 
    natiso-ind  ν τ  WkSGrpNatIso (ω₂ ∘2Mw ν) μ₃  WkSGrpNatIso (ω₂ ∘2Mw ω₁ ∘2Mw μ₁) μ₃)  x  x) μ₂ τ