module Text.LaTeX.Packages
    ( -- * Packages
      Package
    , PackageOption
      -- * List of packages
      -- ** @doc@
    , doc
      -- ** @exscale@
    , exscale
      -- ** @ifthen@
    , ifthen
      -- ** @latexsym@
    , latexsym
      -- ** @makeidx@
    , makeidx
      -- ** @fontenc@
    , fontenc
    , oT1 , t1
    , t2A, t2B
    , t2C, x2
    , lgr
      -- ** @syntonly@
    , syntonly
    , syntaxonly
      -- ** @inputenc@
    , inputenc
    , applemac
    , macukr
    , latin1
    , koi8_ru
    , ansinew
    , cp1251
    , cp850
    , cp866nav
      -- ** @ucs@
    , ucs
    , utf8x
      -- ** @textcomp@
    , textcomp
    , textdegree
    , textcelsius
    , texteuro
      -- ** @eurosym@
    , eurosym
    , euro
      -- ** @babel@
    , babel
    , selectlanguage
      -- ** @hyperref@
    , hyperref
    , pdftex
    , href
      -- ** @color@
    , colorpkg
    , monochrome
    , dvipsnames
    , nodvipsnames
    , usenames
    , rgb
    , pagecolor
    , color
    , normalcolor
      -- * AMS-LaTeX
    , MathTerm
      -- ** @amsmath@
    , amsmath
    , math
    , equation
    , equation_
    , smash
    , lim , (->>)
    , sums , sums_ , summ
    , sqroot
    , cdot , cdots , vdots , ddots
    , overline
    , overbrace, underbrace
      -- *** Operators
    , (==:) , (/=:)
    , (<=:) , (>=:)
    , (===)
    , (~~) , (~=)
    , (<@) , (>@) , (<=@) , (>=@)
    , (-|) , (|-) , (-/)
    , (/@)
    , (|.|)
    , (+-) , (-+)
    , (<*>)
    , (*:) , (^:) , (!:)
      -- *** Math Mode Accents
    , hat , widehat
    , tilde , widetilde
    , grave , bar
    , acute , mathring
    , check , dot
    , vec , breve
    , ddot
      -- *** Greek Alphabet
    , alpha
    , beta
    , gamma , gamma_
    , delta , delta_
    , epsilon , varepsilon
    , zeta
    , eta
    , theta , vartheta , theta_
    , iota
    , kappa
    , lambda , lambda_
    , mu
    , nu
    , xi , xi_
    , varpi , pi_
    , rho , varrho
    , sigma , varsigma , sigma_
    , tau
    , upsilon, upsilon_
    , phi , varphi, phi_
    , chi
    , psi, psi_
    , omega, omega_
    -- *** Mathematical Functions
    -- *** Symbols
    , dagger , ddagger
    , forall
    -- *** Others
    , binom
    , proof
    ) where

import Data.List (intersperse)
import Data.Monoid

import Data.String.Combinators (braces,fromShow,between)

import Text.LaTeX.Monad
import Text.LaTeX.Define
import Text.LaTeX.Arguments
import Text.LaTeX.Result

type Package = LaTeX

type PackageOption = LaTeX

doc :: Package
doc = "doc"

exscale :: Package
exscale = "exscale"

ifthen :: Package
ifthen = "ifthen"

latexsym :: Package
latexsym = "latexsym"

makeidx :: Package
makeidx = "makeidx"

fontenc :: Package
fontenc = "fontenc"

oT1 :: Encoding
oT1 = "0T1"

t1 :: Encoding
t1 = "T1"

t2A :: Encoding
t2A = "T2A"

t2B :: Encoding
t2B = "T2B"

t2C :: Encoding
t2C = "T2C"

x2 :: Encoding
x2 = "X2"

lgr :: Encoding
lgr = "LGR"

syntonly :: Package
syntonly = "syntonly"

syntaxonly :: LaTeX
syntaxonly = comm0 "syntaxonly"

inputenc :: Package
inputenc = "inputenc"

applemac :: Encoding
applemac = "applemac"

macukr :: Encoding
macukr = "macukr"

latin1 :: Encoding
latin1 = "latin1"

koi8_ru :: Encoding
koi8_ru = "koi8-ru"

ansinew :: Encoding
ansinew = "ansinew"

cp1251 :: Encoding
cp1251 = "cp1251"

cp850 :: Encoding
cp850 = "cp850"

cp866nav :: Encoding
cp866nav = "cp866nav"

ucs :: Package
ucs = "ucs"

utf8x :: Encoding
utf8x = "utf8x"

textcomp :: Package
textcomp = "textcomp"

textdegree :: LaTeX
textdegree = comm0 "textdegree"

textcelsius :: LaTeX
textcelsius = comm0 "textcelsius"

texteuro :: LaTeX
texteuro = comm0 "texteuro"

eurosym :: Package
eurosym = "eurosym"

euro :: LaTeX
euro = comm0 "euro"

babel :: Package
babel = "babel"

selectlanguage :: Language -> LaTeX
selectlanguage = comm1 "selectlanguage"

hyperref :: Package
hyperref = "hyperref"

pdftex :: PackageOption
pdftex = "pdftex"

href :: URL -> Text -> LaTeX
href = comm5 "href"

colorpkg :: Package
colorpkg = "color"

monochrome :: PackageOption
monochrome = "monochrome"

dvipsnames :: PackageOption
dvipsnames = "dvipsnames"

nodvipsnames :: PackageOption
nodvipsnames = "nodvipsnames"

usenames :: PackageOption
usenames = "usenames"

rgb :: Float -> Float -> Float -> Color
rgb r g b = do "[rgb]"
               braces . lx . mconcat . intersperse (toResult ",") $ map fromShow [r,g,b]

pagecolor :: Color -> LaTeX
pagecolor = (comm0_ "pagecolor" >>)

color :: Color -> LaTeX
color = (comm0_ "color" >>)

normalcolor :: LaTeX
normalcolor = comm0 "normalcolor"

----------------------------------
---------- AMS-LaTeX -------------

-- LaTeXM numeric instances.

inOp :: LaTeXM a -> (LaTeXM a -> LaTeXM a -> LaTeXM a)
inOp op x y = do x ; op ; y

inOp_ :: LaTeXM a -> (MathTerm -> MathTerm -> MathTerm)
inOp_ op x y = do x ; op ; y

inOpCom = inOp_ . comm0

genOp :: (LaTeX -> LaTeX -> LaTeX) -> (LaTeXM a -> LaTeXM a -> LaTeXM a)
genOp op x y = genlx $ op (ungenlx x) (ungenlx y)

(==:) = inOp_ "="
(/=:) = inOpCom "neq"
(<=:) = inOpCom "leq"
(>=:) = inOpCom "geq"
(===) = inOpCom "equiv"
(~~)  = inOpCom "sim"
(~=)  = inOpCom "simeq"

(<@)  = inOpCom "subset"
(>@)  = inOpCom "supset"
(<=@) = inOpCom "subseteq"
(>=@) = inOpCom "supseteq"
(-|)  = inOpCom "in"
(|-)  = inOpCom "ni"
(-/)  = inOpCom "notin"
(/@)  = inOpCom "setminus"

(|.|) = inOpCom "parallel"

(+-)  = inOpCom "pm"
(-+)  = inOpCom "mp"

(<*>) = inOpCom "star"

instance Num (LaTeXM a) where
 (+) = inOp "+"
 (-) = inOp "-"
 (*) = (>>)
 negate = (comm0 "not" >>)
 fromInteger = lxanyw

(*:) :: MathTerm -> MathTerm -> MathTerm
(*:) = inOp cdot

instance Fractional (LaTeXM a) where
 (/) = genOp $ comm5 "frac"
 fromRational = lxanyw . (fromRational :: Rational -> Float)

instance Floating (LaTeXM a) where
 pi = genlx $ comm0 "pi"
 exp = (comm0 "exp" >>)
 log = (comm0 "log" >>)
 sqrt = genlx . sqroot [] . ungenlx
 (**) = genOp (^:)
 sin = (comm0 "sin" >>)
 cos = (comm0 "cos" >>)
 tan = (comm0 "tan" >>)
 asin = (comm0 "arcsin" >>)
 acos = (comm0 "arccos" >>)
 atan = (comm0 "arctan" >>)
 sinh = (comm0 "sinh" >>)
 cosh = (comm0 "cosh" >>)
 tanh = (comm0 "tanh" >>)

-- AMS-Math

type MathTerm = LaTeX

amsmath :: Package
amsmath = "amsmath"

math :: MathTerm -> LaTeX
math = between "$" "$"

equation :: MathTerm -> LaTeX
equation = env "equation"

equation_ :: MathTerm -> LaTeX
equation_ = env "equation*"

smash :: LaTeX -> LaTeX
smash = comm1 "smash"

text :: LaTeX -> LaTeX
text = comm1 "text"

(^:) :: MathTerm -> MathTerm -> MathTerm
x ^: y = do x ; "^" ; braces y

(!:) :: MathTerm -> MathTerm -> MathTerm
x !: y = do x ; "_" ; braces y

lim :: MathTerm
lim = comm0 "lim"

(->>) :: MathTerm -> MathTerm -> MathTerm
x ->> y = do x ; comm0 "to" ; y

sums :: MathTerm
sums = comm0 "sum"

sums_ :: MathTerm
sums_ = comm0_ "sum"

summ :: MathTerm -> MathTerm -> MathTerm
summ x y = sums_ !: x ^: y

sqroot :: [MathTerm] -> MathTerm -> MathTerm
sqroot = comm4 "sqrt"

cdot :: MathTerm
cdot = comm0 "cdot"

cdots :: MathTerm
cdots = comm0 "cdots"

vdots :: MathTerm
vdots = comm0 "vdots"

ddots :: MathTerm
ddots = comm0 "ddots"

overline :: MathTerm -> MathTerm
overline = comm1 "overline"

overbrace :: MathTerm -> MathTerm
overbrace = comm1 "overbrace"

underbrace :: MathTerm -> MathTerm
underbrace = comm1 "underbrace"

-- Math Mode Accents

hat       = comm1 "hat"
grave     = comm1 "grave"
bar       = comm1 "bar"
acute     = comm1 "acute"
mathring  = comm1 "mathring"
check     = comm1 "check"
dot       = comm1 "dot"
vec       = comm1 "vec"
breve     = comm1 "breve"
tilde     = comm1 "tilde"
ddot      = comm1 "ddot"
widehat   = comm1 "widehat"
widetilde = comm1 "widetilde"

-- Greek Alphabet

alpha = comm0 "alpha"
beta = comm0 "beta"
gamma = comm0 "gamma"
gamma_ = comm0 "Gamma"
delta = comm0 "delta"
delta_ = comm0 "Delta"
epsilon = comm0 "epsilon"
varepsilon = comm0 "varepsilon"
zeta = comm0 "zeta"
eta = comm0 "eta"
theta = comm0 "theta"
vartheta = comm0 "vartheta"
theta_ = comm0 "Theta"
iota = comm0 "iota"
kappa = comm0 "kappa"
lambda = comm0 "lambda"
lambda_ = comm0 "Lambda"
mu = comm0 "mu"
nu = comm0 "nu"
xi = comm0 "xi"
xi_ = comm0 "Xi"
pi = comm0 "pi"
varpi = comm0 "varpi"
pi_ = comm0 "Pi"
rho = comm0 "rho"
varrho = comm0 "varrho"
sigma = comm0 "sigma"
varsigma = comm0 "varsigma"
sigma_ = comm0 "Sigma"
tau = comm0 "tau"
upsilon = comm0 "upsilon"
upsilon_ = comm0 "Upsilon"
phi = comm0 "phi"
varphi = comm0 "varphi"
phi_ = comm0 "Phi"
chi = comm0 "chi"
psi = comm0 "psi"
psi_ = comm0 "Psi"
omega = comm0 "omega"
omega_ = comm0 "Omega"

-- Some mathematical functions

-- Symbols

dagger :: LaTeX
dagger = comm0 "dag"

ddagger :: LaTeX
ddagger = comm0 "ddag"

forall :: LaTeX
forall = comm0 "forall"

-- Others

binom :: MathTerm -> MathTerm -> MathTerm
binom = comm5 "binom"

proof :: LaTeX -> LaTeX
proof = env "proof"