{-# OPTIONS --without-K --safe --lossy-unification #-}
-- lossy unification is required to complete type-checking

open import Categories.Bicategory
open import Categories.Bicategory.LocalCoequalizers

module Categories.Bicategory.Construction.Bimodules {o  e t} (𝒞 : Bicategory o  e t) (localCoeq : LocalCoequalizers 𝒞) where
open import Level using (_⊔_)
open import Data.Product using (_,_)

import Categories.Bicategory.Extras as Bicat
open Bicat 𝒞

open import Categories.Bicategory.Monad using (Monad)
open import Categories.Bicategory.Monad.Bimodule using (Bimodule; id-bimodule)

open import Categories.Category.Construction.Bimodules {𝒞 = 𝒞} using ()renaming (Bimodules to 1-Bimodules)
open import Categories.Category using (Category)
private
  module 1-Bimodules M₁ M₂ = Category (1-Bimodules M₁ M₂)

open import Categories.NaturalTransformation.NaturalIsomorphism using (niHelper)
open import Categories.Morphism using (_≅_)

open import Categories.Bicategory.Construction.Bimodules.TensorproductOfBimodules localCoeq using () renaming (Tensorproduct to infixr 30 _⊗₀_)
open import Categories.Bicategory.Construction.Bimodules.TensorproductOfHomomorphisms localCoeq using () renaming (Tensorproduct to infixr 30 _⊗₁_)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Functorial localCoeq
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Associator localCoeq using (associator-⊗)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Associator.Naturality localCoeq using (α⇒-⊗-natural)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Unitor localCoeq using (module Left-Unitor; module Right-Unitor)
open Left-Unitor using (unitorˡ-⊗)
open Right-Unitor using (unitorʳ-⊗)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Unitor.Naturality localCoeq
  using (module Left-Unitor-natural; module Right-Unitor-natural)
open Left-Unitor-natural using (λ⇒-⊗-natural)
open Right-Unitor-natural using (ρ⇒-⊗-natural)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Coherence.Pentagon localCoeq using (pentagon-⊗)
open import Categories.Bicategory.Construction.Bimodules.Tensorproduct.Coherence.Triangle localCoeq using (triangle-⊗)

Bimodules : Bicategory (o    e) (  e) e (o    e  t)
Bimodules = record
  { enriched = record
    { Obj = Monad 𝒞
    ; hom = 1-Bimodules
    ; id = λ {M}  record
    { F₀ = λ _  id-bimodule M
    ; F₁ = λ _  1-Bimodules.id M M
    ; identity = hom.Equiv.refl
    ; homomorphism = hom.Equiv.sym (1-Bimodules.identity² M M)
    ; F-resp-≈ = λ _  hom.Equiv.refl
    }
    ;  = record
      { F₀ = λ (B₂ , B₁)  B₂ ⊗₀ B₁
      ; F₁ = λ (h₂ , h₁)  h₂ ⊗₁ h₁
      ; identity = λ {(B₂ , B₁)}  Identity.⊗₁-resp-id₂ B₂ B₁
      ; homomorphism = λ {_} {_} {_} {(g₂ , g₁)} {(h₂ , h₁)}  Composition.⊗₁-distr-∘ᵥ h₂ h₁ g₂ g₁
      ; F-resp-≈ = λ {_} {_} {(h₂ , h₁)} {(h'₂ , h'₁)} (e₂ , e₁)  ≈Preservation.⊗₁-resp-≈ h₂ h'₂ h₁ h'₁ e₂ e₁
      }
    ; ⊚-assoc = niHelper record
      { η = λ ((B₃ , B₂) , B₁)  _≅_.from (associator-⊗ {B₃ = B₃} {B₂} {B₁})
      ; η⁻¹ = λ ((B₃ , B₂) , B₁)  _≅_.to (associator-⊗ {B₃ = B₃} {B₂} {B₁})
      ; commute = λ ((f₃ , f₂) , f₁)  α⇒-⊗-natural f₃ f₂ f₁
      ; iso = λ ((B₃ , B₂) , B₁)  _≅_.iso (associator-⊗ {B₃ = B₃} {B₂} {B₁})
      }
    ; unitˡ = niHelper record
      { η = λ (_ , B)  _≅_.from (unitorˡ-⊗ {B = B})
      ; η⁻¹ = λ (_ , B)  _≅_.to (unitorˡ-⊗ {B = B})
      ; commute = λ (_ , f)  λ⇒-⊗-natural f
      ; iso = λ (_ , B)  _≅_.iso (unitorˡ-⊗ {B = B})
      }
    ; unitʳ = niHelper record
      { η = λ (B , _)  _≅_.from (unitorʳ-⊗ {B = B})
      ; η⁻¹ = λ (B , _)  _≅_.to (unitorʳ-⊗ {B = B})
      ; commute = λ (f , _)  ρ⇒-⊗-natural f
      ; iso = λ (B , _)  _≅_.iso (unitorʳ-⊗ {B = B})
      }
    }
  ; triangle = λ {_} {_} {_} {B₁} {B₂}  triangle-⊗ {B₂ = B₂} {B₁}
  ; pentagon = λ {_} {_} {_} {_} {_} {B₁} {B₂} {B₃} {B₄}  pentagon-⊗ {B₄ = B₄} {B₃} {B₂} {B₁}
  }