{-# OPTIONS --safe --postfix-projections #-}

module Cubical.Data.FinSet.Binary.Large where

open import Cubical.Functions.Embedding
open import Cubical.Functions.Involution

open import Cubical.Foundations.Equiv
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Univalence

open import Cubical.Data.Bool
open import Cubical.Data.Sigma

open import Cubical.HITs.PropositionalTruncation

private
  variable
     : Level

isBinary : Type   Type 
isBinary B =  Bool  B ∥₁

Binary :    Type _
Binary  = Σ (Type ) isBinary

isBinary→isSet : ∀{B : Type }  isBinary B  isSet B
isBinary→isSet {B} = rec isPropIsSet λ eqv  isOfHLevelRespectEquiv 2 eqv isSetBool

private
  Σ≡Prop²
    : ∀{ ℓ'} {A : Type } {B : A  Type ℓ'}
     {w x : Σ A B}
     isOfHLevelDep 1 B
     (p q : w  x)
     cong fst p  cong fst q
     p  q
  Σ≡Prop² _ _ _ r i j .fst = r i j
  Σ≡Prop² {B = B} {w} {x} Bprp p q r i j .snd
    = isPropDep→isSetDep Bprp (w .snd) (x .snd) (cong snd p) (cong snd q) r i j


BinaryEmbedding : isEmbedding (λ(B : Binary )  map-snd isBinary→isSet B)
BinaryEmbedding w x = isoToIsEquiv theIso
  where
  open Iso
  f = map-snd isBinary→isSet

  theIso : Iso (w  x) (f w  f x)
  theIso .fun = cong f
  theIso .inv p i .fst = p i .fst
  theIso .inv p i .snd
    = ∥∥-isPropDep (Bool ≃_) (w .snd) (x .snd)  i  p i .fst) i
  theIso .rightInv p
    = Σ≡Prop² (isOfHLevel→isOfHLevelDep 1  _  isPropIsSet)) _ p refl
  theIso .leftInv p
    = Σ≡Prop² (∥∥-isPropDep (Bool ≃_)) _ p refl

Base : Binary _
Base .fst = Bool
Base .snd =  idEquiv Bool ∣₁

Loop : Base  Base
Loop i .fst = notEq i
Loop i .snd = ∥∥-isPropDep (Bool ≃_) (Base .snd) (Base .snd) notEq i

private
  notEq² : Square notEq refl refl notEq
  notEq² = involPath² {f = not} notnot

Loop² : Square Loop refl refl Loop
Loop² i j .fst = notEq² i j
Loop² i j .snd
  = isPropDep→isSetDep' (∥∥-isPropDep (Bool ≃_))
      notEq² (cong snd Loop) refl refl (cong snd Loop) i j

isGroupoidBinary : isGroupoid (Binary )
isGroupoidBinary
  = Embedding-into-hLevel→hLevel 2
      (map-snd isBinary→isSet , BinaryEmbedding)
      (isOfHLevelTypeOfHLevel 2)

record BinStructure (B : Type ) : Type  where
  field
    base : B
    loop : base  base
    loop² : Square loop refl refl loop
    trunc : isGroupoid B

structure₀ : BinStructure (Binary ℓ-zero)
structure₀ .BinStructure.base = Base
structure₀ .BinStructure.loop = Loop
structure₀ .BinStructure.loop² = Loop²
structure₀ .BinStructure.trunc = isGroupoidBinary

module Parameterized (B : Type ) where
  Baseᴾ : Bool  B  Binary 
  Baseᴾ P = B ,  P ∣₁

  Loopᴾ : (P Q : Bool  B)  Baseᴾ P  Baseᴾ Q
  Loopᴾ P Q i = λ where
      .fst  ua first i
      .snd  ∥∥-isPropDep (Bool ≃_)  P ∣₁  Q ∣₁ (ua first) i
    where
    first : B  B
    first = compEquiv (invEquiv P) Q

  Loopᴾ² : (P Q R : Bool  B)  Square (Loopᴾ P Q) (Loopᴾ P R) refl (Loopᴾ Q R)
  Loopᴾ² P Q R i = Σ≡Prop  _  squash₁) (S i)
    where
    PQ : B  B
    PQ = compEquiv (invEquiv P) Q
    PR : B  B
    PR = compEquiv (invEquiv P) R
    QR : B  B
    QR = compEquiv (invEquiv Q) R
    Q-Q : Bool  Bool
    Q-Q = compEquiv Q (invEquiv Q)

    PQRE : compEquiv PQ QR  PR
    PQRE = compEquiv PQ QR
             ≡[ i ]⟨ compEquiv-assoc (invEquiv P) Q QR (~ i) 
           compEquiv (invEquiv P) (compEquiv Q QR)
             ≡[ i ]⟨ compEquiv (invEquiv P) (compEquiv-assoc Q (invEquiv Q) R i) 
           compEquiv (invEquiv P) (compEquiv Q-Q R)
             ≡[ i ]⟨ compEquiv (invEquiv P) (compEquiv (invEquiv-is-rinv Q i) R) 
           compEquiv (invEquiv P) (compEquiv (idEquiv _) R)
             ≡[ i ]⟨ compEquiv (invEquiv P) (compEquivIdEquiv R i) 
           PR 

    PQR : ua PQ  ua QR  ua PR
    PQR = ua PQ  ua QR
            ≡[ i ]⟨ uaCompEquiv PQ QR (~ i) 
          ua (compEquiv PQ QR)
            ≡⟨ cong ua PQRE 
          ua PR 

    S : Square (ua PQ) (ua PR) refl (ua QR)
    S i j
      = hcomp  k  λ where
            (j = i0)  B
            (i = i0)  compPath-filler (ua PQ) (ua QR) (~ k) j
            (i = i1)  ua PR j
            (j = i1)  ua QR (i  ~ k))
          (PQR i j)