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

open import lib.Basics
open import lib.NType2
open import lib.types.TLevel
open import lib.types.Sigma
open import lib.types.Pi

module lib.types.Groupoid where

record GroupoidStructure {i j} {El : Type i} (Arr : El  El  Type j)
  (_ :  x y  has-level 0 (Arr x y)) : Type (lmax i j) where
  field
    ident :  {x}  Arr x x
    inv :  {x y}  Arr x y  Arr y x
    comp :  {x y z}  Arr x y  Arr y z  Arr x z
    unit-l :  {x y} (a : Arr x y)  comp ident a == a
    assoc :  {x y z w} (a : Arr x y) (b : Arr y z) (c : Arr z w)
               comp (comp a b) c == comp a (comp b c)
    inv-l :  {x y} (a : Arr x y)  comp (inv a) a == ident

  private
    infix 80 _⊙_
    _⊙_ = comp

  abstract
    inv-r  :  {x y} (a : Arr x y)  a  inv a == ident
    inv-r a =
      a  inv a                           =⟨ ! $ unit-l (a  inv a) 
      ident  (a  inv a)                 =⟨ ! $ inv-l (inv a) |in-ctx _⊙ (a  inv a) 
      (inv (inv a)  inv a)  (a  inv a) =⟨ assoc (inv (inv a)) (inv a) (a  inv a) 
      inv (inv a)  (inv a  (a  inv a)) =⟨ ! $ assoc (inv a) a (inv a) |in-ctx inv (inv a) ⊙_ 
      inv (inv a)  ((inv a  a)  inv a) =⟨ inv-l a |in-ctx  h  inv (inv a)  (h  inv a)) 
      inv (inv a)  (ident  inv a)       =⟨ unit-l (inv a) |in-ctx inv (inv a) ⊙_ 
      inv (inv a)  inv a                 =⟨ inv-l (inv a) 
      ident                               =∎

    unit-r :  {x y} (a : Arr x y)  a  ident == a
    unit-r a =
      a  ident          =⟨ ! (inv-l a) |in-ctx a ⊙_ 
      a  (inv a  a)    =⟨ ! $ assoc a (inv a) a 
      (a  inv a)  a    =⟨ inv-r a |in-ctx _⊙ a 
      ident  a          =⟨ unit-l a 
      a                  =∎

record PreGroupoid i j : Type (lsucc (lmax i j)) where
  constructor groupoid
  field
    El : Type i
    Arr : El  El  Type j
    Arr-level :  x y  has-level 0 (Arr x y)
    groupoid-struct : GroupoidStructure Arr Arr-level