-- |
-- Module: Symtegration.Integration
-- Description: Symbolically integrates mathematical expressions.
-- Copyright: Copyright 2025 Yoo Chung
-- License: Apache-2.0
-- Maintainer: dev@chungyc.org
module Symtegration.Integration (integrate) where

import Data.Foldable (asum)
import Data.Text (Text)
import Symtegration.Integration.Exponential qualified as Exponential
import Symtegration.Integration.Parts qualified as Parts
import Symtegration.Integration.Powers qualified as Powers
import Symtegration.Integration.Rational qualified as Rational
import Symtegration.Integration.Substitution qualified as Substitution
import Symtegration.Integration.Sum qualified as Sum
import Symtegration.Integration.Term qualified as Term
import Symtegration.Integration.Trigonometric qualified as Trigonometric
import Symtegration.Symbolic
import Symtegration.Symbolic.Simplify

-- |
-- Return the indefinite integral of a mathematical expression given
-- its symbolic representation.  It will return 'Nothing' if it is
-- unable to derive an integral.  This will not apply any simplification.
integrate :: Text -> Expression -> Maybe Expression
integrate :: Text -> Expression -> Maybe Expression
integrate Text
v Expression
e = [Maybe Expression] -> Maybe Expression
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([Maybe Expression] -> Maybe Expression)
-> [Maybe Expression] -> Maybe Expression
forall a b. (a -> b) -> a -> b
$ ((Text -> Expression -> Maybe Expression) -> Maybe Expression)
-> [Text -> Expression -> Maybe Expression] -> [Maybe Expression]
forall a b. (a -> b) -> [a] -> [b]
map (\Text -> Expression -> Maybe Expression
f -> Text -> Expression -> Maybe Expression
f Text
v Expression
e') [Text -> Expression -> Maybe Expression]
withTermSum
  where
    e' :: Expression
e' = Text -> Expression -> Expression
simplifyForVariable Text
v Expression
e

-- | Functions which directly integrate.
base :: [Text -> Expression -> Maybe Expression]
base :: [Text -> Expression -> Maybe Expression]
base = [Text -> Expression -> Maybe Expression
Powers.integrate, Text -> Expression -> Maybe Expression
Exponential.integrate, Text -> Expression -> Maybe Expression
Trigonometric.integrate, Text -> Expression -> Maybe Expression
Rational.integrate]

-- | Includes integration of a term using other integration functions.
withTerm :: [Text -> Expression -> Maybe Expression]
withTerm :: [Text -> Expression -> Maybe Expression]
withTerm =
  [Text -> Expression -> Maybe Expression]
base
    [Text -> Expression -> Maybe Expression]
-> [Text -> Expression -> Maybe Expression]
-> [Text -> Expression -> Maybe Expression]
forall a. [a] -> [a] -> [a]
++ [ [Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Term.integrate [Text -> Expression -> Maybe Expression]
base,
         [Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Substitution.integrate [Text -> Expression -> Maybe Expression]
base,
         [Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Parts.integrate [[Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Term.integrate [Text -> Expression -> Maybe Expression]
base],
         [Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Term.integrate [[Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Substitution.integrate [Text -> Expression -> Maybe Expression]
base, [Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Parts.integrate [[Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Term.integrate [Text -> Expression -> Maybe Expression]
base]]
       ]

-- | Includes integration of a sum of terms.
withTermSum :: [Text -> Expression -> Maybe Expression]
withTermSum :: [Text -> Expression -> Maybe Expression]
withTermSum = [Text -> Expression -> Maybe Expression]
withTerm [Text -> Expression -> Maybe Expression]
-> [Text -> Expression -> Maybe Expression]
-> [Text -> Expression -> Maybe Expression]
forall a. [a] -> [a] -> [a]
++ [[Text -> Expression -> Maybe Expression]
-> Text -> Expression -> Maybe Expression
Sum.integrate [Text -> Expression -> Maybe Expression]
withTerm]