-- Before we can talk about power objects in RT
-- we need to use propositional resizing to get
-- a copy of A-valued predicates in Type ℓ'

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Equiv
open import Cubical.Data.Empty
open import Cubical.Data.Sigma
open import Realizability.PropResizing
open import Realizability.CombinatoryAlgebra

module Realizability.Topos.ResizedPredicate
  {}
  {A : Type }
  (ca : CombinatoryAlgebra A)
  (isNonTrivial : CombinatoryAlgebra.s ca  CombinatoryAlgebra.k ca  )
  (resizing : hPropResizing )
  where

open import Realizability.Tripos.Prealgebra.Predicate {ℓ' = } {ℓ'' = } ca
open import Realizability.Topos.Object {ℓ' = } {ℓ'' = } ca isNonTrivial

open CombinatoryAlgebra ca
open Predicate renaming (isSetX to isSetPredicateBase)

smallHProp = resizing .fst
smallHProp≃hProp = resizing .snd

ResizedPredicate : Type   Type 
ResizedPredicate X = Σ[ rel  (X  A  smallHProp) ] isSet X

PredicateΣ≃ResizedPredicate :  X  PredicateΣ X  ResizedPredicate X
PredicateΣ≃ResizedPredicate X =
  Σ-cong-equiv-prop
    (equivΠ
      (idEquiv X)
       x 
        equivΠ
          (idEquiv A)
          λ a 
            smallHProp≃hProp))
     _  isPropIsSet)
     _  isPropIsSet)
     _ answer  answer)
     _ answer  answer)

Predicate≃ResizedPredicate :  X  Predicate X  ResizedPredicate X
Predicate≃ResizedPredicate X = compEquiv (Predicate≃PredicateΣ X) (PredicateΣ≃ResizedPredicate X)

isSetResizedPredicate :  {X}  isSet (ResizedPredicate X)
isSetResizedPredicate {X} = isOfHLevelRespectEquiv 2 (Predicate≃ResizedPredicate X) (isSetPredicate X)

ResizedPredicate≃Predicate :  X  ResizedPredicate X  Predicate X
ResizedPredicate≃Predicate X = invEquiv (Predicate≃ResizedPredicate X)

toPredicate :  {X}  ResizedPredicate X  Predicate X
toPredicate {X} ϕ = equivFun (ResizedPredicate≃Predicate X) ϕ

fromPredicate :  {X}  Predicate X  ResizedPredicate X
fromPredicate {X} ϕ = equivFun (Predicate≃ResizedPredicate X) ϕ

compIsIdEquiv :  X  compEquiv (Predicate≃ResizedPredicate X) (ResizedPredicate≃Predicate X)  idEquiv (Predicate X)
compIsIdEquiv X = invEquiv-is-rinv (Predicate≃ResizedPredicate X)

compIsIdFunc :  {X}  (p : Predicate X)  toPredicate (fromPredicate p)  p
compIsIdFunc {X} p i = equivFun (compIsIdEquiv X i) p

module ResizedPredicateProps {X} (perX : PartialEquivalenceRelation X) where
  open PartialEquivalenceRelation

  entailmentResizedPredicate :  (ϕ ψ : ResizedPredicate X)  A  Type 
  entailmentResizedPredicate ϕ ψ r =  (x : X) (a : A) (⊩ϕx : a   toPredicate ϕ  x)  (r  a)   toPredicate ψ  x

  isPropEntailmentResizedPredicate :  ϕ ψ a  isProp (entailmentResizedPredicate ϕ ψ a)
  isPropEntailmentResizedPredicate ϕ ψ a =
    isPropΠ λ x  isPropΠ λ b  isPropΠ λ _  (toPredicate ψ) .isPropValued _ _

  isStrictResizedPredicate :  (ϕ : ResizedPredicate X)  A  Type 
  isStrictResizedPredicate ϕ r =  (x : X) (a : A) (⊩ϕx : a   toPredicate ϕ  x)  (r  a)   perX .equality  (x , x)

  isPropIsStrictResizedPredicate :  ϕ r  isProp (isStrictResizedPredicate ϕ r)
  isPropIsStrictResizedPredicate ϕ r =
    isPropΠ λ x  isPropΠ λ a  isPropΠ λ _  perX .equality .isPropValued _ _

  isRelationalResizedPredicate :  (ϕ : ResizedPredicate X)  A  Type 
  isRelationalResizedPredicate ϕ r =
     (x x' : X) (a b : A) (⊩x~x' : a   perX .equality  (x , x')) (⊩ϕx : b   toPredicate ϕ  x)  (r  a  b)   toPredicate ϕ  x'

  isPropIsRelationalResizedPredicate :  ϕ r  isProp (isRelationalResizedPredicate ϕ r)
  isPropIsRelationalResizedPredicate ϕ r =
    isPropΠ λ x  isPropΠ λ x'  isPropΠ λ a  isPropΠ λ b  isPropΠ λ _  isPropΠ λ _  toPredicate ϕ .isPropValued _ _