{-# OPTIONS --safe #-}

module Cubical.Homotopy.Loopspace where

open import Cubical.Core.Everything

open import Cubical.Data.Nat

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Pointed
open import Cubical.Foundations.Pointed.Homogeneous
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.GroupoidLaws
open import Cubical.HITs.SetTruncation
open import Cubical.HITs.Truncation hiding (elim2) renaming (rec to trRec)
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Transport
open import Cubical.Foundations.Equiv.HalfAdjoint
open import Cubical.Foundations.Function
open import Cubical.Foundations.Path
open import Cubical.Foundations.Equiv.HalfAdjoint
open import Cubical.Foundations.Equiv
open import Cubical.Functions.Morphism
open import Cubical.Data.Sigma
open Iso

{- loop space of a pointed type -}
Ω : { : Level}  Pointed   Pointed 
Ω (_ , a) = ((a  a) , refl)

{- n-fold loop space of a pointed type -}
Ω^_ :  {}    Pointed   Pointed 
(Ω^ 0) p = p
(Ω^ (suc n)) p = Ω ((Ω^ n) p)

{- loop space map -}
Ω→ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
       (A →∙ B)  (Ω A →∙ Ω B)
fst (Ω→ {A = A} {B = B} (f , p)) q = sym p ∙∙ cong f q ∙∙ p
snd (Ω→ {A = A} {B = B} (f , p)) = ∙∙lCancel p

Ω^→ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (n : )
   (A →∙ B)  ((Ω^ n) A →∙ (Ω^ n) B)
Ω^→ zero f = f
Ω^→ (suc n) f = Ω→ (Ω^→ n f)

{- loop space map functoriality (missing pointedness proof) -}
Ω→∘ :  { ℓ' ℓ''} {A : Pointed } {B : Pointed ℓ'} {C : Pointed ℓ''}
  (g : B →∙ C) (f : A →∙ B)
    p  Ω→ (g ∘∙ f) .fst p  (Ω→ g ∘∙ Ω→ f) .fst p
Ω→∘ g f p k i =
  hcomp
     j  λ
      { (i = i0)  compPath-filler' (cong (g .fst) (f .snd)) (g .snd) (~ k) j
      ; (i = i1)  compPath-filler' (cong (g .fst) (f .snd)) (g .snd) (~ k) j
      })
    (g .fst (doubleCompPath-filler (sym (f .snd)) (cong (f .fst) p) (f .snd) k i))

Ω→∘∙ :  { ℓ' ℓ''} {A : Pointed } {B : Pointed ℓ'} {C : Pointed ℓ''}
  (g : B →∙ C) (f : A →∙ B)
   Ω→ (g ∘∙ f)  (Ω→ g ∘∙ Ω→ f)
Ω→∘∙ g f = →∙Homogeneous≡ (isHomogeneousPath _ _) (funExt (Ω→∘ g f))

Ω→const :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
           Ω→ {A = A} {B = B} ((λ _  pt B) , refl)  ((λ _  refl) , refl)
Ω→const = →∙Homogeneous≡ (isHomogeneousPath _ _) (funExt λ _  sym (rUnit _))

{- Ω→ is a homomorphism -}
Ω→pres∙filler :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (f : A →∙ B)
         (p q : typ (Ω A))
         I  I  I  fst B
Ω→pres∙filler f p q i j k =
  hfill
     k  λ
       { (i = i0)  doubleCompPath-filler (sym (snd f)) (cong (fst f) (p  q)) (snd f) k j
        ; (i = i1) 
          (doubleCompPath-filler
            (sym (snd f)) (cong (fst f) p) (snd f) k
          doubleCompPath-filler
            (sym (snd f)) (cong (fst f) q) (snd f) k) j
       ; (j = i0)  snd f k
       ; (j = i1)  snd f k})
    (inS (cong-∙ (fst f) p q i j))
    k

Ω→pres∙ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (f : A →∙ B)
         (p q : typ (Ω A))
         fst (Ω→ f) (p  q)  fst (Ω→ f) p  fst (Ω→ f) q
Ω→pres∙ f p q i j = Ω→pres∙filler f p q i j i1

Ω→pres∙reflrefl :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (f : A →∙ B)
                   Ω→pres∙ {A = A} {B = B} f refl refl
                    cong (fst (Ω→ f)) (sym (rUnit refl))
                    snd (Ω→ f)
                    rUnit _
                    cong₂ _∙_ (sym (snd (Ω→ f))) (sym (snd (Ω→ f)))
Ω→pres∙reflrefl {A = A} {B = B} =
  →∙J  b₀ f  Ω→pres∙ {A = A} {B = (fst B , b₀)} f refl refl
                    cong (fst (Ω→ f)) (sym (rUnit refl))
                    snd (Ω→ f)
                    rUnit _
                    cong₂ _∙_ (sym (snd (Ω→ f))) (sym (snd (Ω→ f))))
       λ f  lem f
          cong (cong (fst (Ω→ (f , refl))) (sym (rUnit refl)) ∙_)
                (((lUnit (cong₂ _∙_ (sym (snd (Ω→ (f , refl))))
                                    (sym (snd (Ω→ (f , refl))))))
                 cong (_∙ (cong₂ _∙_ (sym (snd (Ω→ (f , refl))))
                                      (sym (snd (Ω→ (f , refl))))))
                   (sym (rCancel (snd (Ω→ (f , refl))))))
                 sym (assoc (snd (Ω→ (f , refl)))
                  (sym (snd (Ω→ (f , refl))))
                    (cong₂ _∙_ (sym (snd (Ω→ (f , refl))))
                               (sym (snd (Ω→ (f , refl)))))))
  where
  lem : (f : fst A  fst B)  Ω→pres∙ (f , refl)  _  snd A)  _  snd A) 
       i  fst (Ω→ (f , refl)) (rUnit  _  snd A) (~ i))) 
       i  snd (Ω→ (f , refl)) (~ i)  snd (Ω→ (f , refl)) (~ i))
  lem f k i j =
    hcomp  r  λ { (i = i0)  doubleCompPath-filler
                                   refl (cong f ((λ _  pt A)  refl)) refl (r  k) j
                    ; (i = i1)  (∙∙lCancel  _  f (pt A)) (~ r)
                                  ∙∙lCancel  _  f (pt A)) (~ r)) j
                    ; (j = i0)  f (snd A)
                    ; (j = i1)  f (snd A)
                    ; (k = i0)  Ω→pres∙filler {A = A} {B = fst B , f (pt A)}
                                   (f , refl) refl refl i j r
                    ; (k = i1)  compPath-filler
                                   ((λ i  fst (Ω→ (f , refl))
                                                (rUnit  _  snd A) (~ i))))
                                   ((λ i  snd (Ω→ (f , refl)) (~ i)
                                           snd (Ω→ (f , refl)) (~ i))) r i j})
     (hcomp  r  λ { (i = i0)  doubleCompPath-filler refl (cong f (rUnit  _  pt A) r)) refl k j
                    ; (i = i1)  rUnit  _  f (pt A)) (r  k) j
                    ; (j = i0)  f (snd A)
                    ; (j = i1)  f (snd A)
                    ; (k = i0)  cong-∙∙-filler f  _  pt A)  _  pt A)  _  pt A) r i j
                    ; (k = i1)  fst (Ω→ (f , refl)) (rUnit  _  snd A) (~ i  r)) j})
             (rUnit  _  f (pt A)) k j))

{- Ω^→ is homomorphism -}
Ω^→pres∙ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (f : A →∙ B)
         (n : )
         (p q : typ ((Ω^ (suc n)) A))
         fst (Ω^→ (suc n) f) (p  q)
          fst (Ω^→ (suc n) f) p  fst (Ω^→ (suc n) f) q
Ω^→pres∙ {A = A} {B = B} f n p q = Ω→pres∙ (Ω^→ n f) p q

Ω^→∘∙ :  { ℓ' ℓ''} {A : Pointed } {B : Pointed ℓ'} {C : Pointed ℓ''} (n : )
  (g : B →∙ C) (f : A →∙ B)
   Ω^→ n (g ∘∙ f)  (Ω^→ n g ∘∙ Ω^→ n f)
Ω^→∘∙ zero g f = refl
Ω^→∘∙ (suc n) g f = cong Ω→ (Ω^→∘∙ n g f)  Ω→∘∙ (Ω^→ n g) (Ω^→ n f)

Ω^→const :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (n : )
           Ω^→ {A = A} {B = B} n ((λ _  pt B) , refl)
           ((λ _  snd ((Ω^ n) B)) , refl)
Ω^→const zero = refl
Ω^→const (suc n) = cong Ω→ (Ω^→const n)  Ω→const

isEquivΩ→ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
            (f : (A →∙ B))
            isEquiv (fst f)  isEquiv (Ω→ f .fst)
isEquivΩ→ {B = (B , b)} =
  uncurry λ f 
    J  b y  isEquiv f
              isEquiv  q   i  y (~ i)) ∙∙  i  f (q i)) ∙∙ y))
      λ eqf  subst isEquiv (funExt (rUnit  cong f))
                     (isoToIsEquiv (congIso (equivToIso (f , eqf))))

isEquivΩ^→ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (n : )
            (f : A →∙ B)
            isEquiv (fst f)
            isEquiv (Ω^→ n f .fst)
isEquivΩ^→ zero f iseq = iseq
isEquivΩ^→ (suc n) f iseq = isEquivΩ→ (Ω^→ n f) (isEquivΩ^→ n f iseq)

Ω≃∙ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
      (e : A ≃∙ B)
      (Ω A) ≃∙ (Ω B)
fst (fst (Ω≃∙ e)) = fst (Ω→ (fst (fst e) , snd e))
snd (fst (Ω≃∙ e)) = isEquivΩ→ (fst (fst e) , snd e) (snd (fst e))
snd (Ω≃∙ e) = snd (Ω→ (fst (fst e) , snd e))

Ω≃∙pres∙ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
      (e : A ≃∙ B)
      (p q : typ (Ω A))
      fst (fst (Ω≃∙ e)) (p  q)
      fst (fst (Ω≃∙ e)) p
      fst (fst (Ω≃∙ e)) q
Ω≃∙pres∙ e p q = Ω→pres∙ (fst (fst e) , snd e) p q

Ω^≃∙ :  { ℓ'} {A : Pointed } {B : Pointed ℓ'} (n : )
      (e : A ≃∙ B)
      ((Ω^ n) A) ≃∙ ((Ω^ n) B)
Ω^≃∙ zero e = e
fst (fst (Ω^≃∙ (suc n) e)) =
  fst (Ω→ (fst (fst (Ω^≃∙ n e)) , snd (Ω^≃∙ n e)))
snd (fst (Ω^≃∙ (suc n) e)) =
  isEquivΩ→ (fst (fst (Ω^≃∙ n e)) , snd (Ω^≃∙ n e)) (snd (fst (Ω^≃∙ n e)))
snd (Ω^≃∙ (suc n) e) =
  snd (Ω→ (fst (fst (Ω^≃∙ n e)) , snd (Ω^≃∙ n e)))

ΩfunExtIso :  { ℓ'} (A : Pointed ) (B : Pointed ℓ')
   Iso (typ (Ω (A →∙ B ))) (A →∙ Ω B)
fst (fun (ΩfunExtIso A B) p) x = funExt⁻ (cong fst p) x
snd (fun (ΩfunExtIso A B) p) i j = snd (p j) i
fst (inv (ΩfunExtIso A B) (f , p) i) x = f x i
snd (inv (ΩfunExtIso A B) (f , p) i) j = p j i
rightInv (ΩfunExtIso A B) _ = refl
leftInv (ΩfunExtIso A B) _ = refl

relax→∙Ω-Iso :  { ℓ'} {A : Pointed } {B : Pointed ℓ'}
   Iso (Σ[ b  fst B ] (fst A  b  pt B))
         (A →∙ (Ω B))
Iso.fun (relax→∙Ω-Iso {A = A}) (b , p) =  a  sym (p (pt A))  p a) , lCancel (p (snd A))
Iso.inv (relax→∙Ω-Iso {B = B}) a = (pt B) , (fst a)
Iso.rightInv (relax→∙Ω-Iso) a =
  →∙Homogeneous≡ (isHomogeneousPath _ _)
    (funExt λ x  cong (_∙ fst a x) (cong sym (snd a))  sym (lUnit (fst a x)))
Iso.leftInv (relax→∙Ω-Iso {A = A}) (b , p) =
  ΣPathP (sym (p (pt A))
       , λ i a j  compPath-filler' (sym (p (pt A))) (p a) (~ i) j)


{- Commutativity of loop spaces -}
isComm∙ :  {} (A : Pointed )  Type 
isComm∙ A = (p q : typ (Ω A))  p  q  q  p

private
  mainPath :  {} {A : Pointed } (n : )  (α β : typ ((Ω^ (2 + n)) A))
             i  α i  refl)   i  refl  β i)
              i  refl  β i)   i  α i  refl)
  mainPath n α β i =  j  α (j  ~ i)  β (j  i))  λ j  α (~ i  j)  β (i  j)

EH-filler :  {} {A : Pointed } (n : )  typ ((Ω^ (2 + n)) A)
   typ ((Ω^ (2 + n)) A)  I  I  I  _
EH-filler {A = A} n α β i j z =
  hfill  k  λ { (i = i0)  ((cong  x  rUnit x (~ k)) α)
                                 cong  x  lUnit x (~ k)) β) j
                  ; (i = i1)  ((cong  x  lUnit x (~ k)) β)
                                 cong  x  rUnit x (~ k)) α) j
                  ; (j = i0)  rUnit refl (~ k)
                  ; (j = i1)  rUnit refl (~ k)})
        (inS (mainPath n α β i j)) z

{- Eckmann-Hilton -}
EH :  {} {A : Pointed } (n : )  isComm∙ ((Ω^ (suc n)) A)
EH {A = A} n α β i j = EH-filler n α β i j i1

{- Lemmas for the syllepsis : EH α β ≡ (EH β α) ⁻¹ -}

EH-refl-refl :  {} {A : Pointed } (n : )
              EH {A = A} n refl refl  refl
EH-refl-refl {A = A} n k i j =
  hcomp  r  λ { (k = i1)  (refl   _  basep)) j
                  ; (j = i0)  rUnit basep (~ r  ~ k)
                  ; (j = i1)  rUnit basep (~ r  ~ k)
                  ; (i = i0)  (refl   _  lUnit basep (~ r  ~ k))) j
                  ; (i = i1)  (refl   _  lUnit basep (~ r  ~ k))) j})
        (((cong  x  rUnit x (~ k))  _  basep))
          cong  x  lUnit x (~ k))  _  basep)) j)
  where
  basep = snd (Ω ((Ω^ n) A))

{- Generalisations of EH α β when α or β is refl -}
EH-gen-l :  {} {A : Pointed } (n : )  {x y : typ ((Ω^ (suc n)) A)} (α : x  y)
        α  refl  refl  α
EH-gen-l { = } {A = A} n {x = x} {y = y} α i j z =
  hcomp  k  λ { (i = i0)  ((cong  x  rUnit x (~ k)) α)  refl) j z
                  ; (i = i1)  (refl  cong  x  rUnit x (~ k)) α) j z
                  ; (j = i0)  rUnit (refl {x = x z}) (~ k) z
                  ; (j = i1)  rUnit (refl {x = y z}) (~ k) z
                  ; (z = i0)  x i1
                  ; (z = i1)  y i1})
        (((λ j  α (j  ~ i)  refl)  λ j  α (~ i  j)  refl) j z)

EH-gen-r :  {} {A : Pointed } (n : )  {x y : typ ((Ω^ (suc n)) A)} (β : x  y)
         refl  β  β  refl
EH-gen-r {A = A} n {x = x} {y = y} β i j z =
  hcomp  k  λ { (i = i0)  (refl  cong  x  lUnit x (~ k)) β) j z
                  ; (i = i1)  ((cong  x  lUnit x (~ k)) β)  refl) j z
                  ; (j = i0)  lUnit  k  x (k  z)) (~ k) z
                  ; (j = i1)  lUnit  k  y (k  z)) (~ k) z
                  ; (z = i0)  x i1
                  ; (z = i1)  y i1})
        (((λ j  refl  β (j  i))  λ j  refl  β (i  j)) j z)

{- characterisations of EH α β when α or β is refl  -}
EH-α-refl :  {} {A : Pointed } (n : )
              (α : typ ((Ω^ (2 + n)) A))
              EH n α refl  sym (rUnit α)  lUnit α
EH-α-refl {A = A} n α i j k =
  hcomp  r  λ { (i = i0)  EH-gen-l n  i  α (i  r)) j k
                  ; (i = i1)  (sym (rUnit λ i  α (i  r))  lUnit λ i  α (i  r)) j k
                  ; (j = i0)  ((λ i  α (i  r))  refl) k
                  ; (j = i1)  (refl   i  α (i  r))) k
                  ; (k = i0)  refl
                  ; (k = i1)  α r})
        ((EH-refl-refl n  sym (lCancel (rUnit refl))) i j k)

EH-refl-β :  {} {A : Pointed } (n : )
              (β : typ ((Ω^ (2 + n)) A))
              EH n refl β  sym (lUnit β)  rUnit β
EH-refl-β {A = A} n β i j k =
  hcomp  r  λ { (i = i0)  EH-gen-r n  i  β (i  r)) j k
                  ; (i = i1)  (sym (lUnit λ i  β (i  r))  rUnit λ i  β (i  r)) j k
                  ; (j = i0)  (refl   i  β (i  r))) k
                  ; (j = i1)  ((λ i  β (i  r))  refl) k
                  ; (k = i0)  refl
                  ; (k = i1)  β r})
        ((EH-refl-refl n  sym (lCancel (rUnit refl))) i j k)

syllepsis :  {} {A : Pointed } (n : ) (α β : typ ((Ω^ 3) A))
          EH 0 α β  sym (EH 0 β α)
syllepsis {A = A} n α β k i j =
  hcomp  r  λ { (i = i0)  i=i0 r j k
                  ; (i = i1)  i=i1 r j k
                  ; (j = i0)  j-filler r j k
                  ; (j = i1)  j-filler r j k
                  ; (k = i0)  EH-filler 1 α β i j r
                  ; (k = i1)  EH-filler 1 β α (~ i) j r})
        (btm-filler (~ k) i j)
  where
  guy = snd (Ω (Ω A))

  btm-filler : I  I  I  typ (Ω (Ω A))
  btm-filler j i k =
    hcomp  r
       λ {(j = i0)  mainPath 1 β α (~ i) k
          ; (j = i1)  mainPath 1 α β i k
          ; (i = i0)  (cong  x  EH-α-refl 0 x r (~ j)) α
                        cong  x  EH-refl-β 0 x r (~ j)) β) k
          ; (i = i1)  (cong  x  EH-refl-β 0 x r (~ j)) β
                        cong  x  EH-α-refl 0 x r (~ j)) α) k
          ; (k = i0)  EH-α-refl 0 guy r (~ j)
          ; (k = i1)  EH-α-refl 0 guy r (~ j)})
      (((λ l  EH 0 (α (l  ~ i)) (β (l  i)) (~ j))
        λ l  EH 0 (α (l  ~ i)) (β (l  i)) (~ j)) k)

  link : I  I  I  _
  link z i j =
    hfill  k  λ { (i = i1)  refl
                    ; (j = i0)  rUnit refl (~ i)
                    ; (j = i1)  lUnit guy (~ i  k)})
          (inS (rUnit refl (~ i  ~ j))) z

  i=i1 : I  I  I  typ (Ω (Ω A))
  i=i1 r j k =
    hcomp  i  λ { (r = i0)  (cong  x  compPath-filler (sym (lUnit x)) (rUnit x) i k) β
                                 cong  x  compPath-filler (sym (rUnit x)) (lUnit x) i k) α) j
                    ; (r = i1)  (β  α) j
                    ; (k = i0)  (cong  x  lUnit x (~ r)) β 
                                   cong  x  rUnit x (~ r)) α) j
                    ; (k = i1)  (cong  x  rUnit x (~ r  i)) β 
                                   cong  x  lUnit x (~ r  i)) α) j
                    ; (j = i0)  link i r k
                    ; (j = i1)  link i r k})
          (((cong  x  lUnit x (~ r  ~ k)) β
            cong  x  rUnit x (~ r  ~ k)) α)) j)

  i=i0 : I  I  I  typ (Ω (Ω A))
  i=i0 r j k =
    hcomp  i  λ { (r = i0)  (cong  x  compPath-filler (sym (rUnit x)) (lUnit x) i k) α
                                 cong  x  compPath-filler (sym (lUnit x)) (rUnit x) i k) β) j
                    ; (r = i1)  (α  β) j
                    ; (k = i0)  (cong  x  rUnit x (~ r)) α 
                                   cong  x  lUnit x (~ r)) β) j
                    ; (k = i1)  (cong  x  lUnit x (~ r  i)) α 
                                   cong  x  rUnit x (~ r  i)) β) j
                    ; (j = i0)  link i r k
                    ; (j = i1)  link i r k})
          ((cong  x  rUnit x (~ r  ~ k)) α
            cong  x  lUnit x (~ r  ~ k)) β) j)

  j-filler : I  I  I  typ (Ω (Ω A))
  j-filler r i k =
    hcomp  j  λ { (i = i0)  link j r k
                    ; (i = i1)  link j r k
                    ; (r = i0)  compPath-filler (sym (rUnit guy))
                                                  (lUnit guy) j k
                    ; (r = i1)  refl
                    ; (k = i0)  rUnit guy (~ r)
                    ; (k = i1)  rUnit guy (j  ~ r)})
          (rUnit guy (~ r  ~ k))

------ Ωⁿ⁺¹ A ≃ Ωⁿ(Ω A) ------
flipΩPath : { : Level} {A : Pointed } (n : )
                 ((Ω^ (suc n)) A)  (Ω^ n) (Ω A)
flipΩPath {A = A} zero = refl
flipΩPath {A = A} (suc n) = cong Ω (flipΩPath {A = A} n)

flipΩIso : { : Level} {A : Pointed } (n : )
               Iso (fst ((Ω^ (suc n)) A)) (fst ((Ω^ n) (Ω A)))
flipΩIso {A = A} n = pathToIso (cong fst (flipΩPath n))

flipΩIso⁻pres· : { : Level} {A : Pointed } (n : )
                       (f g : fst ((Ω^ (suc n)) (Ω A)))
                       inv (flipΩIso (suc n)) (f  g)
                       (inv (flipΩIso (suc n)) f)
                       (inv (flipΩIso (suc n)) g)
flipΩIso⁻pres· {A = A} n f g i =
    transp  j  flipΩPath {A = A} n (~ i  ~ j) .snd
                  flipΩPath n (~ i  ~ j) .snd) i
                  (transp  j  flipΩPath {A = A} n (~ i  ~ j) .snd
                  flipΩPath n (~ i  ~ j) .snd) (~ i) f
                  transp  j  flipΩPath {A = A} n (~ i  ~ j) .snd
                  flipΩPath n (~ i  ~ j) .snd) (~ i) g)

flipΩIsopres· : { : Level} {A : Pointed } (n : )
                       (f g : fst (Ω ((Ω^ (suc n)) A)))
                       fun (flipΩIso (suc n)) (f  g)
                       (fun (flipΩIso (suc n)) f)
                       (fun (flipΩIso (suc n)) g)
flipΩIsopres· n =
  morphLemmas.isMorphInv _∙_ _∙_
    (inv (flipΩIso (suc n)))
    (flipΩIso⁻pres· n)
    (fun (flipΩIso (suc n)))
    (Iso.leftInv (flipΩIso (suc n)))
    (Iso.rightInv (flipΩIso (suc n)))

flipΩrefl :  {} {A : Pointed } (n : )
   fun (flipΩIso {A = A} (suc n)) refl  refl
flipΩrefl {A = A} n j =
  transp  i₁  fst (Ω (flipΩPath {A = A} n ((i₁  j)))))
         j (snd (Ω (flipΩPath n j)))

---- Misc. ----

isCommA→isCommTrunc :  {} {A : Pointed } (n : )  isComm∙ A
                     isOfHLevel (suc n) (typ A)
                     isComm∙ ( typ A  (suc n) ,  pt A )
isCommA→isCommTrunc {A = (A , a)} n comm hlev p q =
    ((λ i j  (leftInv (truncIdempotentIso (suc n) hlev) ((p  q) j) (~ i)))
 ∙∙  i  cong {B = λ _   A  (suc n) }  x   x )
                 (cong (trRec hlev  x  x)) (p  q)))
 ∙∙  i  cong {B = λ _   A  (suc n) }  x   x )
                 (congFunct {A =  A  (suc n)} {B = A} (trRec hlev  x  x)) p q i)))
  ((λ i  cong {B = λ _   A  (suc n) }  x   x )
                 (comm (cong (trRec hlev  x  x)) p) (cong (trRec hlev  x  x)) q) i))
 ∙∙  i  cong {B = λ _   A  (suc n) }  x   x )
                 (congFunct {A =  A  (suc n)} {B = A} (trRec hlev  x  x)) q p (~ i)))
 ∙∙  i j  (leftInv (truncIdempotentIso (suc n) hlev) ((q  p) j) i)))

ptdIso→comm :  { ℓ'} {A : Pointed } {B : Type ℓ'} (e : Iso (typ A) B)
   isComm∙ A  isComm∙ (B , fun e (pt A))
ptdIso→comm {A = (A , a)} {B = B} e comm p q =
       sym (rightInv (congIso e) (p  q))
    ∙∙ (cong (fun (congIso e)) ((invCongFunct e p q)
                            ∙∙ (comm (inv (congIso e) p) (inv (congIso e) q))
                            ∙∙ (sym (invCongFunct e q p))))
    ∙∙ rightInv (congIso e) (q  p)

{- Homotopy group version -}
π-comp :  {} {A : Pointed } (n : )   typ ((Ω^ (suc n)) A) ∥₂
        typ ((Ω^ (suc n)) A) ∥₂   typ ((Ω^ (suc n)) A) ∥₂
π-comp n = elim2  _ _  isSetSetTrunc) λ p q   p  q ∣₂

EH-π :  {} {A : Pointed } (n : ) (p q :  typ ((Ω^ (2 + n)) A) ∥₂)
                π-comp (1 + n) p q  π-comp (1 + n) q p
EH-π  n = elim2  x y  isOfHLevelPath 2 isSetSetTrunc _ _)
                             λ p q  cong ∣_∣₂ (EH n p q)