{-# OPTIONS --rewriting #-}

module Pi  where

open import Equality
open import EquationalReasoning
open import Fibration
open import FunExt
open import Interval
open import Level
open import Path
open import Product

----------------------------------------------------------------------
-- Pi types
----------------------------------------------------------------------
Pi :
  { ℓ' ℓ'' : Level}
  {Γ : Set }
  (A : Γ  Set ℓ')
  (B : Σ Γ A  Set ℓ'')
   ---------------------------
  Γ  Set (ℓ'  ℓ'')
Pi A B x = (a : A x)  B(x , a)

PiAct :
  { ℓ' : Level}
  {Γ : Set }
  (A : Γ  Set ℓ')
  {{_ : isFib A}}
  (B : Σ Γ A  Set ℓ')
  {{_ : isFib B}}
  (x y : Γ)
  (p : x ~ y)
   ------------------
  Pi A B x  Pi A B y
PiAct _ _ _ _ p f a = ~symm (~lift (~symm p) a)  (f (~symm p  a))

PiActId :
  { ℓ' : Level}
  {Γ : Set }
  (A : Γ  Set ℓ')
  {{_ : isFib A}}
  (B : Σ Γ A  Set ℓ')
  {{_ : isFib B}}
  (x  : Γ)
  (f : (a : A x)  B(x , a))
   ---------------------------
  f ~ PiAct A B x x (~refl x) f
PiActId A {{α}} B {{β}} x f =
  ~funext  a 
  path:
    f a
  ~[ ~substrefl β (f a) ]
    ~refl (x , a)  f a
  ~[ ~cong (_∗ f a) (≡to~ (atInj refl)) ]
    ~symm (~cong (x ,_) (~refl a))  f a
  ~[ ~cong (λ{(b , q)  ~symm (~cong (x ,_) q)  f b})
     (~contr (~substrefl α a)) ]
    ~symm (~cong (x ,_) (~substrefl α a))  f (~refl x  a)
  ~[ ~cong  q  (~symm q)  f (~refl x  a)) (~symm (~liftrefl x a)) ] 
    ~symm (~lift (~refl x) a)  f (~refl x  a)
  ~[ ≡to~ (cong  q  ~symm (~lift q a)  f (q  a)) ~symmrefl) ]
    ~symm (~lift (~symm (~refl x)) a)  f ((~symm (~refl x))  a)
  endp)

isFibPi :
  { ℓ' : Level}
  {Γ : Set }
  (A : Γ  Set ℓ')
  {{_ : isFib A}}
  (B : Σ Γ A  Set ℓ')
  {{_ : isFib B}}
   ------------------
  isFib (Pi A B)
isFibPi A B = (PiAct A B , PiActId A B)