{-# OPTIONS --without-K --safe #-}

open import Categories.Category using (Category)

module Categories.Functor.Slice {o  e} (C : Category o  e) where

open import Function using () renaming (id to id→)

open import Categories.Diagram.Pullback C using (Pullback; unglue; Pullback-resp-≈)
open import Categories.Functor using (Functor)
open import Categories.Functor.Properties using ([_]-resp-∘)
open import Categories.Morphism.Reasoning C
open import Categories.Object.Product C

import Categories.Category.Slice as S
import Categories.Category.Construction.Pullbacks as Pbs

open Category C
open HomReasoning
open Equiv

module _ {A : Obj} where
  open S.SliceObj
  open S.Slice⇒

  -- A functor between categories induces one between the corresponding slices at a given object of C.
  Base-F :  {o′ ℓ′ e′} {D : Category o′ ℓ′ e′} (F : Functor C D)  Functor (S.Slice C A) (S.Slice D (Functor.F₀ F A))
  Base-F F = record
    { F₀           = λ s  S.sliceobj (F₁ (arr s))
    ; F₁           = λ s⇒  S.slicearr ([ F ]-resp-∘ ( s⇒))
    ; identity     = identity
    ; homomorphism = homomorphism
    ; F-resp-≈     = F-resp-≈
    }
    where open Functor F

  open S C

  TotalSpace : Functor (Slice A) C
  TotalSpace = record
    { F₀           = Y
    ; F₁           = h
    ; identity     = refl
    ; homomorphism = refl
    ; F-resp-≈     = id→
    }

  module _ (product : {X : Obj}  Product A X) where

    private
      module product {X} = Product (product {X})
      open product

    -- this is adapted from proposition 1.33 of Aspects of Topoi (Freyd, 1972)
    ConstantFamily : Functor C (Slice A)
    ConstantFamily = record
      { F₀ = λ _  sliceobj π₁
      ; F₁ = λ f  slicearr ([ product  product ]π₁∘×  identityˡ)
      ; identity = id×id product
      ; homomorphism = sym [ product  product  product ]id×∘id×
      ; F-resp-≈ = λ f≈g  ⟨⟩-cong₂ refl (∘-resp-≈ˡ f≈g)
      }