\import Algebra.Monoid
\import Algebra.Ring.Graded
\import Algebra.Ring.Ideal
\import Data.Array
\import Data.Or
\import Function.Meta
\import Logic
\import Logic.Meta
\import Meta
\import Paths
\import Paths.Meta
\open GradedCRing
\open AddMonoid

\record HomogenIdeal \extends Ideal {
  \override S : GradedCRing
  | isHomogenIdeal {l : Array S} : isHomogenArray l -> contains (AddMonoid.BigSum l) ->  (x : l) (contains x)
} \where {
  \func hasHomogenGen {R : GradedCRing} (I : Ideal R)
    => \Sigma (U : R -> \Prop) (\Pi (x : R) -> U x ->  (n : Nat) (isHomogen x n)) (\Pi (x : R) -> I x <-> Ideal.sclosure U x)

  -- | A homogeneous ideal has a set of homogeneous generators
  \func toGen (I : HomogenIdeal) : hasHomogenGen I
    => \let U x =>  (l : Array S) (isHomogenArray l) (i : Fin l.len) (l i = x) (I (BigSum l))
       \in (U, \lam x => TruncP.map __ \lam (l,f,n,p,c) => (n, rewriteI p (f n)),
            \lam x => (\lam Ix => TruncP.map (homogen-decomp x) \lam (l,f,p) => (mkArray \lam j => later (1, (l j, inP (l, f, j, idp, rewrite p Ix))), inv p *> pmap BigSum (exts \lam j => inv ide-left)),
                       Ideal.sclosure-univ $ later \lam y (inP (l,f,i,p,c)) => transport I p (isHomogenIdeal f c i)))

  -- | If an ideal has a set of homogeneous generators, then it is homogeneous
  \func fromGen {R : GradedCRing} (I : Ideal R) (h : TruncP (hasHomogenGen I)) : HomogenIdeal \cowith
    | Ideal => I
    | isHomogenIdeal {l} lh s j =>
      \have | (inP H) => h
            | (inP (l',p)) => (H.3 (BigSum l)).1 s
            | (inP (N,f,q)) => sum-decomp (map (\lam s => (s.1,s.2.1)) l') (\lam i => H.2 (l' i).2.1 (l' i).2.2)
      \in \case similar-eq (R.homogen-similar lh (\lam n => homogen-FinSum $ (f n).5) (p *> q)) j \with {
            | inl r => transportInv I r.2 $ finSum \lam k => later $ ideal-left $ (H.3 _).2 $ Ideal.sclosure-superset (l' _).2.2
            | inr r => transportInv I r contains_zro
          }
}

\func irrelevantIdeal (R : GradedCRing) : HomogenIdeal R
  => HomogenIdeal.fromGen (Ideal.sclosure (\lam x =>  (n : Nat) (isHomogen x (suc n)))) $
      inP (\lam x =>  (n : Nat) (isHomogen x (suc n)), \lam x => TruncP.map __ \lam (n,h) => (suc n, h), \lam x => (\lam c => c, \lam c => c))