{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE InstanceSigs, UndecidableInstances, AllowAmbiguousTypes, ScopedTypeVariables, IncoherentInstances  #-}

module IHP.View.Types
( FormField (..)
, SubmitButton (..)
, FormContext (..)
, InputType (..)
, CSSFramework (..)
, HtmlWithContext
, Layout
)
where

import IHP.Prelude hiding (div)
import qualified Text.Blaze.Html5 as Blaze
import IHP.FlashMessages.Types


type HtmlWithContext context = (?context :: context) => Blaze.Html

-- | A layout is just a function taking a view and returning a new view.
--
-- __Example:__ A very basic html layout.
-- 
-- > myLayout :: Layout
-- > myLayout view = [hsx|
-- >     <html>
-- >         <body>
-- >             {view}
-- >         </body>
-- >     </html>
-- > |]
type Layout = Blaze.Html -> Blaze.Html

data FormField = FormField
    { FormField -> InputType
fieldType :: !InputType
    , FormField -> AttributeValue
fieldName :: !Blaze.AttributeValue
    , FormField -> Text
fieldLabel :: !Text
    , FormField -> Text
fieldValue :: !Text
    , FormField -> Text
fieldInputId :: !Text
    , FormField -> Maybe Text
validatorResult :: !(Maybe Text)
    , FormField -> FormField -> Html
fieldInput :: !(FormField -> Blaze.Html)
    , FormField -> Text
fieldClass :: !Text
    , FormField -> Text
labelClass :: !Text
    , FormField -> Bool
disableLabel :: !Bool
    , FormField -> Bool
disableGroup :: !Bool
    , FormField -> Bool
disableValidationResult :: !Bool
    , FormField -> CSSFramework
cssFramework :: CSSFramework
    , FormField -> Text
helpText :: !Text
    , FormField -> Text
placeholder :: !Text
    , FormField -> Bool
required :: Bool
    , FormField -> Bool
autofocus :: Bool
    }

data SubmitButton = SubmitButton
    { SubmitButton -> Html
label :: Blaze.Html
    , SubmitButton -> Text
buttonClass :: Text
    , SubmitButton -> CSSFramework
cssFramework :: CSSFramework
    }

data FormContext model = FormContext
    { FormContext model -> model
model :: model
    , FormContext model -> Text
formAction :: !Text
    , FormContext model -> CSSFramework
cssFramework :: CSSFramework
    }

data InputType
    = TextInput
    | NumberInput
    | CheckboxInput
    | ColorInput
    | EmailInput
    | HiddenInput
    | TextareaInput
    | DateInput
    | DateTimeInput
    | PasswordInput
    | SelectInput { InputType -> [(Text, Text)]
options :: ![(Text, Text)] }


-- | Render functions to render with bootstrap etc.
--
-- We call this functions with the cssFramework passed to have late binding (like from OOP languages)
data CSSFramework = CSSFramework
    { CSSFramework -> CSSFramework -> FlashMessage -> Html
styledFlashMessage :: CSSFramework -> FlashMessage -> Blaze.Html
    , CSSFramework -> CSSFramework -> [FlashMessage] -> Html
styledFlashMessages :: CSSFramework -> [FlashMessage] -> Blaze.Html
    -- | Renders the full form field calling other functions below
    , CSSFramework -> CSSFramework -> FormField -> Html
styledFormField :: CSSFramework -> FormField -> Blaze.Html
    -- | The primary form submit button
    , CSSFramework -> CSSFramework -> SubmitButton -> Html
styledSubmitButton :: CSSFramework -> SubmitButton -> Blaze.Html
    -- | Class for the primary form submit button
    , CSSFramework -> Text
styledSubmitButtonClass :: Text
    -- | Renders the help text below an input field. Used with @[hsx|{(textField #firstname) { helpText = "Your first name" } }|]@
    , CSSFramework -> CSSFramework -> FormField -> Html
styledFormFieldHelp :: CSSFramework -> FormField -> Blaze.Html
    -- | First class attached to @<input/>@ elements, e.g. @<input class="form-control"/>@
    , CSSFramework -> FormField -> Text
styledInputClass :: FormField -> Text
    -- | When the form validation failed, invalid inputs will have this class
    , CSSFramework -> FormField -> Text
styledInputInvalidClass :: FormField -> Text
    -- | Class applied to the div wrapping the label and input, e.g. @"form-group"@
    , CSSFramework -> Text
styledFormGroupClass :: Text
    -- | Elements that containers the validation error message for a invalid form field
    , CSSFramework -> CSSFramework -> FormField -> Html
styledValidationResult :: CSSFramework -> FormField -> Blaze.Html
    -- | Class name for container of validation error message
    , CSSFramework -> Text
styledValidationResultClass :: Text
    }