{-# OPTIONS --safe --lossy-unification #-}
module Cubical.Algebra.Polynomials.UnivariateHIT.Polyn-nPoly where

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

open import Cubical.Data.Nat renaming (_+_ to _+n_; _·_ to _·n_)
open import Cubical.Data.Vec
open import Cubical.Data.Sigma

open import Cubical.Algebra.DirectSum.DirectSumHIT.Base
open import Cubical.Algebra.Ring
open import Cubical.Algebra.GradedRing.DirectSumFun
open import Cubical.Algebra.CommRing
open import Cubical.Algebra.CommRing.Instances.Polynomials.UnivariatePolyHIT
open import Cubical.Algebra.CommRing.Instances.Polynomials.MultivariatePoly

open import Cubical.Algebra.Polynomials.Multivariate.EquivCarac.Poly0-A
open import Cubical.Algebra.Polynomials.Multivariate.EquivCarac.An[Am[X]]-Anm[X]
open import Cubical.Algebra.Polynomials.Multivariate.EquivCarac.AB-An[X]Bn[X]

open CommRingEquivs renaming (compCommRingEquiv to _∘-ecr_ ; invCommRingEquiv to inv-ecr)

private variable
   : Level


-----------------------------------------------------------------------------
-- Definition

module equiv1 (A'@(A , Astr) : CommRing )
  where

  private
    PA = PolyCommRing A' 1
    PAstr = snd PA
    PA' = nUnivariatePolyHIT A' 1
    PA'str = snd PA'

  open CommRingStr

  directSense : fst (PolyCommRing A' 1)  fst (nUnivariatePolyHIT A' 1)
  directSense = DS-Rec-Set.f _ _ _ _
                (is-set PA'str)
                (0r PA'str)
                 { (n  []) a  base n a})
                (_+_ PA'str)
                (+Assoc PA'str)
                (+IdR PA'str)
                (+Comm PA'str)
                 { (n  [])  base-neutral _ })
                λ { (n  []) a b   base-add _ _ _}

  convSense : fst (nUnivariatePolyHIT A' 1)  fst (PolyCommRing A' 1)
  convSense = DS-Rec-Set.f _ _ _ _
               (is-set PAstr)
               (0r PAstr)
                n a  base (n  []) a)
               (_+_ PAstr)
               (+Assoc PAstr)
               (+IdR PAstr)
               (+Comm PAstr)
                n  base-neutral _)
               λ _ _ _  base-add _ _ _

  retr : (x : fst (PolyCommRing A' 1))  convSense (directSense x)  x
  retr = DS-Ind-Prop.f _ _ _ _  _  is-set PAstr _ _)
         refl
          { (n  []) a  refl})
          {U V} ind-U ind-V  cong₂ (_+_ PAstr) ind-U ind-V)

  sect : (x : fst (nUnivariatePolyHIT A' 1))  (directSense (convSense x)  x)
  sect = DS-Ind-Prop.f _ _ _ _  _  is-set PA'str _ _)
         refl
          n a  refl)
          {U V} ind-U ind-V  cong₂ (_+_ PA'str) ind-U ind-V)

  converseSense-pres· : (x y : fst (PolyCommRing A' 1)) 
                        directSense (_·_ PAstr x y)  _·_ PA'str (directSense x) (directSense y)
  converseSense-pres· = DS-Ind-Prop.f _ _ _ _
                         _  isPropΠ λ _  is-set PA'str _ _)
                         _  refl)
                         { (n  []) a  DS-Ind-Prop.f _ _ _ _  _  is-set PA'str _ _)
                                           refl
                                            { (m  []) b  refl})
                                           λ {U V} ind-U ind-V  cong₂ (_+_ PA'str) ind-U ind-V})
                        λ {U V} ind-U ind-V y  cong₂ (_+_ PA'str) (ind-U y) (ind-V y)

  open Iso

  equivR : CommRingEquiv PA PA'
  fst equivR = isoToEquiv is
    where
    is : Iso (PA .fst) (PA' .fst)
    fun is = directSense
    inv is = convSense
    rightInv is = sect
    leftInv is = retr
  snd equivR = makeIsRingHom refl  _ _  refl) converseSense-pres·


open equiv1

Equiv-Polyn-nPolyHIT : (A' : CommRing )  (n : )  CommRingEquiv (PolyCommRing A' n) (nUnivariatePolyHIT A' n)
Equiv-Polyn-nPolyHIT A' zero = CRE-Poly0-A A'
Equiv-Polyn-nPolyHIT A' (suc n) =       inv-ecr _ _ (CRE-PolyN∘M-PolyN+M A' 1 n)
                               ∘-ecr (lift-equiv-poly _ _ 1 (Equiv-Polyn-nPolyHIT A' n)
                               ∘-ecr equivR (nUnivariatePolyHIT A' n))