module Cubical.Foundations.Smallness where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Univalence
open import Cubical.Data.Sigma
open import Cubical.Displayed.Base

is[_]Small : ( : Level) {ℓ' : Level} (A : Type ℓ')  Type (ℓ-max (ℓ-suc ) ℓ')
is[_]Small  A = Σ (Type ) λ B  B  A

isLocally[_]Small : ( : Level) {ℓ' : Level} (A : Type ℓ')  Type (ℓ-max (ℓ-suc ) ℓ')
isLocally[_]Small  A = (x y : A)  is[  ]Small (x  y)

isSmall-≃-isSmall :   {} {ℓ'} {ℓ''} {A : Type ℓ'} {A' : Type ℓ''}  is[  ]Small A  A  A'  is[  ]Small A'
isSmall-≃-isSmall small equiv .fst = small .fst
isSmall-≃-isSmall small equiv .snd = compEquiv (small .snd) equiv

isSmall≃ :  {} {ℓ'} {ℓ''} {A : Type ℓ'} {A' : Type ℓ''}
   is[  ]Small A
   is[  ]Small A'
   is[  ]Small (A  A')
isSmall≃ smallA smallA' .fst = smallA .fst  smallA' .fst
isSmall≃ smallA smallA' .snd = equivComp (smallA .snd) (smallA' .snd)

isSmall≡ :  {} {ℓ'} {A : Type ℓ'} {A' : Type ℓ'}
   is[  ]Small A
   is[  ]Small A'
   is[  ]Small (A  A')
isSmall≡ smallA smallA' = isSmall-≃-isSmall (isSmall≃ smallA smallA') (invEquiv univalence)

isℓSmallℓ :  {} (A : Type )  is[  ]Small A
isℓSmallℓ A .fst = A
isℓSmallℓ A .snd = idEquiv A

isSmallΣ :  { ℓ' ℓ''} {A : Type ℓ'} {B : A  Type ℓ''}
   is[  ]Small A
   ((a : A)  is[  ]Small (B a))
   is[  ]Small (Σ A B)
isSmallΣ sA sB .fst = Σ[ a'  sA .fst ] sB (sA .snd .fst a') .fst
isSmallΣ sA sB .snd = Σ-cong-equiv (sA .snd)  a'  sB (sA .snd .fst a') .snd)

isSmallΠ :  { ℓ' ℓ''} {A : Type ℓ'} {B : A  Type ℓ''}
   is[  ]Small A
   ((a : A)  is[  ]Small (B a))
   is[  ]Small ((a : A)  B a)
isSmallΠ sA sB .fst = (a' : sA .fst)  sB (sA .snd .fst a') .fst
isSmallΠ sA sB .snd = equivΠ (sA .snd)  a'  sB (sA .snd .fst a') .snd)

-- Evidence that A is locally ℓ-small is the same as an ℓ-valued UARel on A.

module _ { ℓ'} {A : Type } where

  locallySmall→UARel : isLocally[ ℓ' ]Small A  UARel A ℓ'
  locallySmall→UARel lsA .UARel._≅_ x y = lsA x y .fst
  locallySmall→UARel lsA .UARel.ua x y = lsA x y .snd

  UARel→locallySmall : UARel A ℓ'  isLocally[ ℓ' ]Small A
  UARel→locallySmall 𝒮-A x y = (x A.≅ y ) , A.ua x y
    where module A = UARel 𝒮-A