implementation module iTasks.Extensions.JavaScript

import ABC.Interpreter.JavaScript
import ABC.Interpreter.JavaScript.Monad
import Data.Func
import iTasks

appJSWorld :: !(*JSWorld -> *JSWorld) -> Task ()
appJSWorld f = viewInformation [ViewUsing id $ jsEditor f] ()
where
	jsEditor :: !(*JSWorld -> *JSWorld) -> Editor a (?a) | TC a
	jsEditor f = withClientSideInit initUI $ leafEditorToEditor {LeafEditor | onReset = onReset, onEdit = onEdit, onRefresh = onRefresh, writeValue = writeValue}
	where
		onReset attr mval vst = (Ok (uia UIComponent attr, mval, ?None),vst)
		initUI _ me world     = f world
		onEdit () mbVal vst   = (Error "unexpected edit event",vst)
		onRefresh mbVal _ vst   = (Ok (NoChange, mbVal, ?None),vst)
		writeValue _          = Ok ?None

accJSWorld :: !(*JSWorld -> (a, *JSWorld)) -> Task a | iTask a
accJSWorld f = enterInformation [EnterUsing id $ accJSEditor (const f)]

runJSMonad :: st !(JS st a) -> Task a | iTask a
runJSMonad st m = enterInformation [EnterUsing id $ accJSEditor (\me -> runJS st me m)]

accJSEditor :: !(JSVal *JSWorld -> (a, *JSWorld)) -> Editor a (EditorReport a) | JSONEncode{|*|}, JSONDecode{|*|}, TC a
accJSEditor f = withClientSideInit initUI $ leafEditorToEditor {LeafEditor | onReset = onReset, onEdit = onEdit, onRefresh = onRefresh, writeValue = writeValue}
where
	onReset attr mbval vst = (Ok (uia UIComponent attr, mbval, ?None),vst)
	initUI _ me world
		# (value, world) = f me world
		# world          = (me .# "doEditEvent" .$! toJSON (?Just value)) world
		= world
	onEdit e _ vst = (Ok (ChangeUI [SetAttribute "value" (toJSON (fromJust e))] [], e, maybe ?None (?Just o ValidEditor) e),vst)
	onRefresh mbVal _ vst = (Ok (NoChange, mbVal, ?None),vst)
	writeValue _ = Ok EmptyEditor
