{-# OPTIONS --safe #-}

module Multiset.FCM.Order where

open import Multiset.Prelude
open import Multiset.FCM.Base as M

open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Function
  using (flip)
open import Cubical.Foundations.Structure

open import Cubical.Functions.Logic as Logic

open import Cubical.Data.Sigma as Simga

open import Cubical.HITs.PropositionalTruncation as PT
  using
    ( ∣_∣₁
    ; ∥_∥₁
    ; isPropPropTrunc
    )

module _ { : Level} {X : Type } where

  -- ⊕-cancel : ∀ xs {ys₁ ys₂ : M X}
  --   → xs ⊕ ys₁ ≡ xs ⊕ ys₂
  --   → ys₁ ≡ ys₂
  -- ⊕-cancel xs {ys₁} {ys₂} = M.ind {P = λ xs → ∀ ys₁ ys₂ → xs ⊕ ys₁ ≡ xs ⊕ ys₂ → ys₁ ≡ ys₂}
  --   (λ _ → isPropΠ3 λ _ _ _ → isSetM _ _)
  --   {! !} {! !} {! !} xs ys₁ ys₂
  
  _⊆′_ : M X  M X  Type 
  xs ⊆′ ys = Σ[ vs  M X ] xs  vs  ys

  -- isProp-⊆′ : ∀ xs ys → isProp (xs ⊆′ ys)
  -- isProp-⊆′ xs ys = {! !}

  _⊆ₚ_ : M X  M X  hProp 
  -- xs ⊆ₚ ys = ∃[ zs ∶ M X ] (((xs ⊕ zs) ≡ ys) , isSetM _ _)
  xs ⊆ₚ ys = ∃[ zs  M X ] (xs  zs) ≡ₚ ys

  _⊆_ : M X  M X  Type 
  xs  ys =  xs ⊆ₚ ys 

  isProp-⊆ :  {xs ys}  isProp (xs  ys)
  isProp-⊆ = str (_ ⊆ₚ _)

  _⊇ₚ_ : M X  M X  hProp 
  _⊇ₚ_ = flip _⊆ₚ_

  _⊇_ : M X  M X  Type 
  _⊇_ = flip _⊆_

  infix 80 _⊆_ _⊇_
  infix 80 _⊆ₚ_ _⊇ₚ_

  ⊆-refl :  {xs : M X}  xs  xs
  ⊆-refl {xs = xs} =  ε ,  unit' xs ∣₁ ∣₁

  ⊆-trans :  {xs ys zs}
     xs  ys
     ys  zs
     xs  zs
  ⊆-trans {xs = xs} {ys} {zs} = PT.rec2 isProp-⊆ goal where
    step :  {us vs}
       xs  us  ys
       ys  vs  zs
       xs  zs
    step {us} {vs} p q =  us  vs ,  r ∣₁ ∣₁ where
      r =
        xs  (us  vs) ≡⟨ assoc _ _ _ 
        (xs  us)  vs ≡⟨ cong (_⊕ vs) p 
        ys  vs        ≡⟨ q 
        zs 

    goal :
        Σ[ us  M X ]  xs  us  ys ∥₁
       Σ[ vs  M X ]  ys  vs  zs ∥₁
       xs  zs
    goal (us , p-us) (vs , p-vs) = PT.rec2 isProp-⊆ step p-us p-vs

  -- ε-unit-unique : ∀ {xs : M X} es
  --   → xs ⊕ es ≡ xs
  --   → es ≡ ε
  -- ε-unit-unique {xs = xs} = M.ind {P = λ xs → ∀ es → xs ⊕ es ≡ xs → es ≡ ε}
  --   (λ _ → isPropΠ2 λ _ _ → isSetM _ ε) empty* {! !} {! !} xs where
  --   empty* : ∀ es → ε ⊕ es ≡ ε → es ≡ ε
  --   empty* es ε⊕es≡ε =
  --     es ≡⟨ sym (unit es) ⟩
  --     ε ⊕ es ≡⟨ ε⊕es≡ε ⟩
  --     ε ∎

  -- ⊆-antisymm : ∀ {xs ys}
  --   → xs ⊆ ys
  --   → ys ⊆ xs
  --   → xs ≡ ys
  -- ⊆-antisymm {xs} {ys} = PT.rec2 (isSetM _ _) goal where
  --   step : ∀ {us vs}
  --     → xs ⊕ us ≡ ys
  --     → ys ⊕ vs ≡ xs
  --     → xs ≡ ys
  --   step {us} {vs} p q = {! ε-unit-unique (us ⊕ vs) us⊕vs-unitl !} where
  --     us⊕vs-unitl : xs ⊕ (us ⊕ vs) ≡ xs
  --     us⊕vs-unitl =
  --       xs ⊕ (us ⊕ vs) ≡⟨ assoc _ _ _ ⟩
  --       (xs ⊕ us) ⊕ vs ≡⟨ cong (_⊕ vs) p ⟩
  --       ys ⊕ vs ≡⟨ q ⟩
  --       xs ∎

  --   goal :
  --       Σ[ us ∈ M X ] ∥ xs ⊕ us ≡ ys ∥₁
  --     → Σ[ vs ∈ M X ] ∥ ys ⊕ vs ≡ xs ∥₁
  --     → xs ≡ ys
  --   goal (us , p-us) (vs , p-vs) = PT.rec2 (isSetM _ _) step p-us p-vs

  -- ⊆-η-inj : ∀ {x y : X}
  --   → (setX : isSet X)
  --   → η x ⊆ η y
  --   → x ≡ y
  -- ⊆-η-inj setX = PT.rec (setX _ _) λ (zs , p) → {! !}