module Text.YuiGrid.LayoutHints where

import Text.CxML (CssInlineDecl)

data LayoutHints = LayoutHints {
                                inFstSibling :: Bool,
                                cssHints :: [CssInlineDecl],
                                pageAreaHint :: Maybe PageAreaHint,
                                verticalHint :: VerticalHint,
                                columnsQty :: Maybe Int, -- to be used in containers only.
                                columnsQtyVote :: Maybe Int,
                                horizontalHint :: HorizontalHint
                               }

data PageAreaHint = InMain | InHeader | InFooter | InLeftSidebar | InRightSidebar
                    deriving Eq

data VerticalHint = NearTop | Weight Float | NearBottom
                    deriving (Eq, Ord)

data HorizontalHint = ClearSides | NearLeft | HorizWeight Float | NearRight
                      deriving (Eq, Ord)

blankHints :: LayoutHints
blankHints = LayoutHints False [] Nothing (Weight 0) Nothing Nothing (HorizWeight 0)


class HasLayoutHints a where
  modLayoutHints :: (LayoutHints -> LayoutHints) -> a -> a

setInFstSibling, resetInFstSibling :: HasLayoutHints a => a -> a
setInFstSibling = modLayoutHints (\lhs -> lhs {inFstSibling = True} )
resetInFstSibling = modLayoutHints (\lhs -> lhs {inFstSibling = False} )

addCss :: HasLayoutHints a => CssInlineDecl -> a -> a
addCss (cssId, cssRls) = modLayoutHints (\lhs -> lhs {cssHints = (cssId, cssRls):cssHints lhs} )

resetCss :: HasLayoutHints a => a -> a
resetCss = modLayoutHints (\lhs -> lhs {cssHints = [] } )

setPageAreaHint :: HasLayoutHints a => PageAreaHint -> a -> a
setPageAreaHint pahint = modLayoutHints (\lhs -> lhs {pageAreaHint = Just pahint})

setVerticalHint :: HasLayoutHints a => VerticalHint -> a -> a
setVerticalHint vhint = modLayoutHints (\lhs -> lhs {verticalHint = vhint})

setHorizontalHint :: HasLayoutHints a => HorizontalHint -> a -> a
setHorizontalHint hhint = modLayoutHints (\lhs -> lhs {horizontalHint = hhint})

inMain, inHeader, inFooter, inLeftSidebar, inRightSidebar :: HasLayoutHints a => a -> a
inMain = setPageAreaHint InMain
inHeader = setPageAreaHint InHeader
inFooter = setPageAreaHint InFooter
inLeftSidebar = setPageAreaHint InLeftSidebar
inRightSidebar = setPageAreaHint InRightSidebar

nearTop, nearBottom :: HasLayoutHints a => a -> a
nearTop = setVerticalHint NearTop
nearBottom = setVerticalHint NearBottom

weight :: HasLayoutHints a => Float -> a -> a
weight = setVerticalHint . Weight

setColumns, setColumnsVote :: HasLayoutHints a => Int -> a -> a
setColumns n = modLayoutHints (\lhs -> lhs {columnsQty = Just n})
setColumnsVote n = modLayoutHints (\lhs -> lhs {columnsQtyVote = Just n})

resetColumns, resetColumnsVote :: HasLayoutHints a => a -> a
resetColumns = modLayoutHints (\lhs -> lhs {columnsQty = Nothing})
resetColumnsVote = modLayoutHints (\lhs -> lhs {columnsQtyVote = Nothing})

clearSides, nearLeft, nearRight :: HasLayoutHints a => a -> a
clearSides = setHorizontalHint ClearSides
nearLeft = setHorizontalHint NearLeft
nearRight = setHorizontalHint NearRight

horizWeight :: HasLayoutHints a => Float -> a -> a
horizWeight = setHorizontalHint . HorizWeight


applyLayouts :: HasLayoutHints a => [a -> a] -> a -> a
applyLayouts = foldl (.) id


-- Combinators that set specific CSS rules with layout hints

smallMarginBottomCSS, giveBorderCSS :: HasLayoutHints a => a -> a
smallMarginBottomCSS = addCss smallMarginBottomCSSRls
giveBorderCSS = addCss giveBorderCSSRls

smallMarginBottomCSSRls = ("smallMarginBottom", [("margin-bottom","1em")])
giveBorderCSSRls = ("giveBorder", [("border","1px solid black")])