{-# OPTIONS --without-K --rewriting --overlapping-instances #-}

open import HoTT
open import homotopy.HSpace
open import homotopy.EilenbergMacLane1 using (EM₁-level₁)

module homotopy.EM1HSpace where

module EM₁HSpace {i} (G : AbGroup i) where

  private
    module G = AbGroup G

    emloop-commutes : (g g' : G.El)  emloop g  emloop g' == emloop g'  emloop g
    emloop-commutes g g' =
      emloop g  emloop g'
        =⟨ ! (emloop-comp' G.grp g g') 
      emloop (G.comp g g')
        =⟨ ap (emloop' G.grp) (G.comm g g') 
      emloop (G.comp g' g)
        =⟨ emloop-comp' G.grp g' g 
      emloop g'  emloop g =∎

  mult-loop : G.El  (x : EM₁ G.grp)  x == x
  mult-loop g = EM₁-set-elim
    {P = λ x  x == x}
    {{λ {x}  has-level-apply (EM₁-level₁ G.grp) x x}}
    (emloop g)
     g'  ↓-idf=idf-in' (emloop-commutes g g'  ∙=∙' (emloop g') (emloop g)))

  private
    module M = homotopy.EilenbergMacLane1 (fst G) -- makes instances work

    EM₁-endo-Ω-group : Group i
    EM₁-endo-Ω-group = Ω^S-group 0 ⊙[ (EM₁ G.grp  EM₁ G.grp) ,  x  x) ]

    mult-hom : GroupHom G.grp EM₁-endo-Ω-group
    mult-hom = record {f = λ=  mult-loop; pres-comp = pres-comp}
      where
      abstract
        pres-comp' : (g₁ g₂ : G.El) (x : EM₁ G.grp) 
          mult-loop (G.comp g₁ g₂) x == mult-loop g₁ x  mult-loop g₂ x
        pres-comp' g₁ g₂ =
          EM₁-prop-elim
            {P = λ x  mult-loop (G.comp g₁ g₂) x == mult-loop g₁ x  mult-loop g₂ x}
            {{has-level-apply (has-level-apply (EM₁-level₁ G.grp) _ _) _ _}}
            (emloop-comp g₁ g₂)

        pres-comp : (g₁ g₂ : G.El)
           λ= (mult-loop (G.comp g₁ g₂)) ==
            Group.comp EM₁-endo-Ω-group (λ= (mult-loop g₁)) (λ= (mult-loop g₂))
        pres-comp g₁ g₂ =
          ap λ= (λ= (pres-comp' g₁ g₂)) 
          =ₛ-out (λ=-∙ (mult-loop g₁) (mult-loop g₂))

    module MultRec = EM₁Level₁Rec {G = G.grp} {C = EM₁ G.grp  EM₁ G.grp}  x  x) mult-hom

  abstract
    mult : EM₁ G.grp  EM₁ G.grp  EM₁ G.grp
    mult = MultRec.f

    mult-embase-β : mult embase   x  x)
    mult-embase-β = MultRec.embase-β
    {-# REWRITE mult-embase-β #-}

    mult-emloop-β :  g y  ap  x  mult x y) (emloop g) == mult-loop g y
    mult-emloop-β g y =
      ap  x  mult x y) (emloop g)
        =⟨ ap-∘  f  f y) mult (emloop g) 
      app= (ap mult (emloop g)) y
        =⟨ ap  w  app= w y) (MultRec.emloop-β g) 
      app= (λ= (mult-loop g)) y
        =⟨ app=-β (mult-loop g) y 
      mult-loop g y =∎

  H-⊙EM₁ : HSpaceStructure (⊙EM₁ G.grp)
  H-⊙EM₁ = from-alt-h-space $ record { μ = mult; unit-l = unit-l; unit-r = unit-r; coh = coh }
    where
    unit-l : (x : EM₁ G.grp)  mult embase x == x
    unit-l x = idp

    unit-r : (x : EM₁ G.grp)  mult x embase == x
    unit-r = EM₁-set-elim
      {P = λ x  mult x embase == x}
      {{λ {x}  has-level-apply (EM₁-level₁ G.grp) (mult x embase) x}}
      idp
       g  ↓-app=idf-in $
         idp ∙' emloop g
           =⟨ ∙'-unit-l (emloop g) 
         emloop g
           =⟨ ! (mult-emloop-β g embase) 
         ap  z  mult z embase) (emloop g)
           =⟨ ! (∙-unit-r (ap  z  mult z embase) (emloop g))) 
         ap  z  mult z embase) (emloop g)  idp =∎)

    coh : unit-l embase == unit-r embase
    coh = idp

  open HSpaceStructure H-⊙EM₁