{-# OPTIONS --safe #-}
module Cubical.Algebra.Group.Exact where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function

open import Cubical.Data.Unit

open import Cubical.Algebra.Group.Base
open import Cubical.Algebra.Group.Morphisms
open import Cubical.Algebra.Group.MorphismProperties
open import Cubical.Algebra.Group.GroupPath
open import Cubical.Algebra.Group.Instances.Unit

open import Cubical.HITs.PropositionalTruncation as PT


-- TODO : Define exact sequences
-- (perhaps short, finite, ℕ-indexed and ℤ-indexed)

SES→isEquiv :  { ℓ'} {L R : Group ℓ-zero}
   {G : Group } {H : Group ℓ'}
   UnitGroup₀  L
   UnitGroup₀  R
   (lhom : GroupHom L G) (midhom : GroupHom G H) (rhom : GroupHom H R)
   ((x : _)  isInKer midhom x  isInIm lhom x)
   ((x : _)  isInKer rhom x  isInIm midhom x)
   isEquiv (fst midhom)
SES→isEquiv {R = R} {G = G} {H = H} =
  J  L _  UnitGroup₀  R 
      (lhom : GroupHom L G) (midhom : GroupHom G H)
      (rhom : GroupHom H R) 
      ((x : fst G)  isInKer midhom x  isInIm lhom x) 
      ((x : fst H)  isInKer rhom x  isInIm midhom x) 
      isEquiv (fst midhom))
      ((J  R _  (lhom : GroupHom UnitGroup₀ G) (midhom : GroupHom G H)
                   (rhom : GroupHom H R) 
                   ((x : fst G)  isInKer midhom x  isInIm lhom x) 
                   ((x : _)  isInKer rhom x  isInIm midhom x) 
                   isEquiv (fst midhom))
         main))
  where
  main : (lhom : GroupHom UnitGroup₀ G) (midhom : GroupHom G H)
         (rhom : GroupHom H UnitGroup₀) 
         ((x : fst G)  isInKer midhom x  isInIm lhom x) 
         ((x : fst H)  isInKer rhom x  isInIm midhom x) 
         isEquiv (fst midhom)
  main lhom midhom rhom lexact rexact =
    BijectionIsoToGroupEquiv {G = G} {H = H}
      bijIso' .fst .snd
    where
    bijIso' : BijectionIso G H
    BijectionIso.fun bijIso' = midhom
    BijectionIso.inj bijIso' x inker =
      PT.rec (GroupStr.is-set (snd G) _ _)
            s  sym (snd s)  IsGroupHom.pres1 (snd lhom))
           (lexact _ inker)
    BijectionIso.surj bijIso' x = rexact x refl

-- exact sequence of 4 groups. Useful for the proof of π₄S³
record Exact4 { ℓ' ℓ'' ℓ''' : Level} (G : Group )
  (H : Group ℓ') (L : Group ℓ'') (R : Group ℓ''')
  (G→H : GroupHom G H) (H→L : GroupHom H L) (L→R : GroupHom L R)
  : Type (ℓ-max  (ℓ-max ℓ' (ℓ-max ℓ'' ℓ'''))) where
  field
    ImG→H⊂KerH→L : (x : fst H)  isInIm G→H x  isInKer H→L x
    KerH→L⊂ImG→H : (x : fst H)  isInKer H→L x  isInIm G→H x

    ImH→L⊂KerL→R : (x : fst L)  isInIm H→L x  isInKer L→R x
    KerL→R⊂ImH→L : (x : fst L)  isInKer L→R x  isInIm H→L x

open Exact4

extendExact4Surjective : { ℓ' ℓ'' ℓ''' ℓ'''' : Level}
  (G : Group ) (H : Group ℓ') (L : Group ℓ'') (R : Group ℓ''') (S : Group ℓ'''')
  (G→H : GroupHom G H) (H→L : GroupHom H L) (L→R : GroupHom L R) (R→S : GroupHom R S)
   isSurjective G→H
   Exact4 H L R S H→L L→R R→S
   Exact4 G L R S (compGroupHom G→H H→L) L→R R→S
ImG→H⊂KerH→L (extendExact4Surjective G H L R S G→H H→L L→R R→S surj ex) x =
  PT.rec (GroupStr.is-set (snd R) _ _)
    (uncurry λ g  J  x _  isInKer L→R x)
      (ImG→H⊂KerH→L ex (fst H→L (fst G→H g))
         (fst G→H g) , refl ∣₁))
KerH→L⊂ImG→H (extendExact4Surjective G H L R S G→H H→L L→R R→S surj ex) x ker =
  PT.rec squash₁
    (uncurry λ y  J  x _  isInIm (compGroupHom G→H H→L) x)
      (PT.map (uncurry
         y  J  y _  Σ[ g  fst G ] fst H→L (fst G→H g)  H→L .fst y)
        (y , refl))) (surj y)))
    (KerH→L⊂ImG→H ex x ker)
ImH→L⊂KerL→R (extendExact4Surjective G H L R S G→H H→L L→R R→S surj ex) =
  ImH→L⊂KerL→R ex
KerL→R⊂ImH→L (extendExact4Surjective G H L R S G→H H→L L→R R→S surj ex) =
  KerL→R⊂ImH→L ex

-- Useful lemma in the proof of π₄S³≅ℤ
transportExact4 : { ℓ' ℓ'' : Level}
                   {G G₂ : Group } {H H₂ : Group ℓ'} {L L₂ : Group ℓ''} {R : Group₀}
                   (G≡G₂ : G  G₂) (H≡H₂ : H  H₂) (L≡L₂ : L  L₂)
                 UnitGroup₀  R
                 (G→H : GroupHom G H) (G₂→H₂ : GroupHom G₂ H₂)
                   (H→L : GroupHom H L) (H₂→L₂ : GroupHom H₂ L₂)
                   (L→R : GroupHom L R)
                 Exact4 G H L R G→H H→L L→R
                 PathP  i  GroupHom (G≡G₂ i) (H≡H₂ i)) G→H G₂→H₂
                 PathP  i  GroupHom (H≡H₂ i) (L≡L₂ i)) H→L H₂→L₂
                 Exact4 G₂ H₂ L₂ UnitGroup₀ G₂→H₂ H₂→L₂ (→UnitHom L₂)
transportExact4 {G = G} {G₂ = G₂} {H = H} {H₂ = H₂} {L = L} {L₂ = L₂} {R = R} =
  J4  G₂ H₂ L₂ R G≡G₂ H≡H₂ L≡L₂ Unit≡R
                 (G→H : GroupHom G H) (G₂→H₂ : GroupHom G₂ H₂)
                   (H→L : GroupHom H L) (H₂→L₂ : GroupHom H₂ L₂)
                   (L→R : GroupHom L R)
                 Exact4 G H L R G→H H→L L→R
                 PathP  i  GroupHom (G≡G₂ i) (H≡H₂ i)) G→H G₂→H₂
                 PathP  i  GroupHom (H≡H₂ i) (L≡L₂ i)) H→L H₂→L₂
                 Exact4 G₂ H₂ L₂ UnitGroup₀ G₂→H₂ H₂→L₂ (→UnitHom L₂))
       G→H G₂→H₂ H→L H₂→L₂ L→R ex pp1 pp2
         J4  G₂→H₂ H₂→L₂ (x : Unit) (y : Unit)
                 pp1 pp2 (_ : tt  x) (_ : tt  x)
              Exact4 G H L UnitGroup₀ G₂→H₂ H₂→L₂ (→UnitHom L))
               ex G₂→H₂ H₂→L₂ tt tt pp1 pp2 refl refl )
      G₂ H₂ L₂ R
  where
  J4 :  { ℓ₂ ℓ₃ ℓ₄ ℓ'} {A : Type }
       {A₂ : Type ℓ₂} {A₃ : Type ℓ₃} {A₄ : Type ℓ₄}
       {x : A} {x₂ : A₂} {x₃ : A₃} {x₄ : A₄}
       (B : (y : A) (z : A₂) (w : A₃) (u : A₄)
        x  y  x₂  z  x₃  w  x₄  u  Type ℓ')
     B x x₂ x₃ x₄ refl refl refl refl
     (y : A) (z : A₂) (w : A₃) (u : A₄)
       (p : x  y) (q : x₂  z) (r : x₃  w) (s : x₄  u)
     B y z w u p q r s
  J4 {x = x} {x₂ = x₂} {x₃ = x₃} {x₄ = x₄} B b y z w u =
    J  y p  (q : x₂  z) (r : x₃  w) (s : x₄  u) 
      B y z w u p q r s)
      (J  z q  (r : x₃  w) (s : x₄  u)  B x z w u refl q r s)
        (J  w r  (s : x₄  u)  B x x₂ w u refl refl r s)
          (J  u s  B x x₂ x₃ u refl refl refl s) b)))