module IHP.IDE.SchemaDesigner.View.Policies.Edit where

import IHP.ViewPrelude
import IHP.IDE.SchemaDesigner.Types
import qualified IHP.IDE.SchemaDesigner.Compiler as Compiler
import IHP.IDE.ToolServer.Types
import IHP.IDE.SchemaDesigner.View.Layout

data EditPolicyView = EditPolicyView
    { EditPolicyView -> [Statement]
statements :: [Statement]
    , EditPolicyView -> Text
tableName :: Text
    , EditPolicyView -> [Column]
columns :: [Column]
    , EditPolicyView -> Statement
policy :: Statement
    }

instance View EditPolicyView where
    html :: EditPolicyView -> Html
html EditPolicyView { [Column]
[Statement]
Text
Statement
policy :: Statement
columns :: [Column]
tableName :: Text
statements :: [Statement]
$sel:policy:EditPolicyView :: EditPolicyView -> Statement
$sel:columns:EditPolicyView :: EditPolicyView -> [Column]
$sel:tableName:EditPolicyView :: EditPolicyView -> Text
$sel:statements:EditPolicyView :: EditPolicyView -> [Statement]
.. } = [hsx|
        <div class="row no-gutters bg-white" id="schema-designer-viewer">
            {renderObjectSelector (zip [0..] statements) (Just tableName)}
            {renderColumnSelector tableName (zip [0..] columns) statements}
        </div>
        {migrationStatus}
        {renderModal modal}
    |]
        where
            modalContent :: Html
modalContent = [hsx|
                <form method="POST" action={UpdatePolicyAction} class="edit-policy">
                    <input type="hidden" name="tableName" value={tableName}/>
                    <!--
                        The hidden name field is required as the user could be changing the name and we don't have any other
                        identifier to refer to the policy besides the name
                    -->
                    <input type="hidden" name="name" value={get #name policy}/>

                    <!-- These will be filled via JS from the ace editors -->
                    <input type="hidden" name="using" value={using}/>
                    <input type="hidden" name="check" value={check}/>

                    <div class="form-group">
                        <input
                            id="nameInput"
                            name="policyName"
                            type="text"
                            class="form-control"
                            autofocus="autofocus"
                            value={get #name policy}
                            />
                    </div>

                    <div class="form-group">
                        <label for="using">Visible if:</label>
                        <textarea
                            id="using"
                            name="using"
                            type="text"
                            class="form-control sql-expression"
                            data-autocomplete-suggestions={autocompleteSuggestions}
                        >{using}</textarea>
                        <small class="form-text text-muted">This SQL expression needs to return True if the row should be visible to the current user. This is the <code>USING</code> condition of the Postgres Policy</small>
                    </div>

                    <div class="form-group">
                        <label for="using">Additionally, allow INSERT and UPDATE only if:</label>
                        <textarea
                            id="check"
                            name="check"
                            type="text"
                            class="form-control sql-expression"
                            data-autocomplete-suggestions={autocompleteSuggestions}
                        >{check}</textarea>
                        <small class="form-text text-muted">Use this to e.g. disallow users changing the user_id to another user's id. This is the <code>CHECK</code> condition of the Postgres Policy</small>
                    </div>

                    <div class="text-right">
                        <button type="submit" class="btn btn-primary">Update Policy</button>
                    </div>
                </form>
            |]
            modalFooter :: Maybe Html
modalFooter = Maybe Html
forall a. Monoid a => a
mempty
            modalCloseUrl :: Text
modalCloseUrl = TablesController -> Text
forall controller. HasPath controller => controller -> Text
pathTo ShowTableAction :: Text -> TablesController
ShowTableAction { Text
$sel:tableName:TablesAction :: Text
tableName :: Text
tableName }
            modalTitle :: Text
modalTitle = Text
"Edit Policy"
            modal :: Modal
modal = Modal :: Html -> Maybe Html -> Text -> Text -> Modal
Modal { Html
$sel:modalContent:Modal :: Html
modalContent :: Html
modalContent, Maybe Html
$sel:modalFooter:Modal :: Maybe Html
modalFooter :: Maybe Html
modalFooter, Text
$sel:modalCloseUrl:Modal :: Text
modalCloseUrl :: Text
modalCloseUrl, Text
$sel:modalTitle:Modal :: Text
modalTitle :: Text
modalTitle }

            using :: Text
using = Proxy "using" -> Statement -> Maybe Expression
forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get IsLabel "using" (Proxy "using")
Proxy "using"
#using Statement
policy
                    Maybe Expression -> (Maybe Expression -> Text) -> Text
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> Text -> (Expression -> Text) -> Maybe Expression -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" Expression -> Text
Compiler.compileExpression

            check :: Text
check = Proxy "check" -> Statement -> Maybe Expression
forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get IsLabel "check" (Proxy "check")
Proxy "check"
#check Statement
policy
                    Maybe Expression -> (Maybe Expression -> Text) -> Text
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> Text -> (Expression -> Text) -> Maybe Expression -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" Expression -> Text
Compiler.compileExpression

            autocompleteSuggestions :: Text
autocompleteSuggestions =
                    [Column]
columns
                    [Column] -> ([Column] -> [Text]) -> [Text]
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> (Column -> Text) -> [Column] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Proxy "name" -> Column -> Text
forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get IsLabel "name" (Proxy "name")
Proxy "name"
#name)
                    [Text] -> ([Text] -> Text) -> Text
forall t1 t2. t1 -> (t1 -> t2) -> t2
|> Text -> [Text] -> Text
intercalate Text
","