import { useState, useEffect } from 'preact/hooks'
import CheapGlkOte from 'cheap-glkote'
import TextBuffer from './OutputBox/TextBuffer/TextBuffer'
import GridBuffer from './OutputBox/GridBuffer/GridBuffer'
import InputBox from './InputBox/InputBox'
import Status from './Status/Status'
import {
Handlers,
unhandledRejectionHandler,
} from './common/playerHandlers'
import * as s from './Player.module.scss'
const INITIAL_STATUS = {
stage: 'loading',
details: ['Preparing'],
}
const runMachine = ({ engine: Engine, wasmBinary, storyfile, handlers }) => {
const { Dialog, GlkOte, send } = CheapGlkOte(handlers)
const instance = new Engine()
instance.init(storyfile, {
Dialog,
GlkOte,
Glk: {},
wasmBinary,
arguments: ['storyfile'],
})
instance.start()
return { send, instance }
}
export default function Player ({
vmParts: { storyfile, engine, wasmBinary },
onFullscreenRequest,
setMenuOpen,
singleWindow,
}) {
const [status, setStatus] = useState(INITIAL_STATUS)
const [windows, setWindows] = useState([])
const [currentWindowId, setCurrentWindowId] = useState(null)
const [inputType, setInputType] = useState(null)
const [inbox, setInbox] = useState([])
const [vm, setVm] = useState(null)
const [sendMessage, setSendMessage] = useState(null)
useEffect(() => {
const handlers = Handlers({
setStatus,
setWindows,
setCurrentWindowId,
setInputType,
setInbox,
})
setVm(runMachine({
engine,
wasmBinary,
storyfile,
handlers,
}))
const rejectionHandler =
unhandledRejectionHandler(handlers.onExit)
window.addEventListener('unhandledrejection', rejectionHandler)
return () => {
setVm(null)
window.removeEventListener('unhandledrejection', rejectionHandler)
}
}, [storyfile, engine, wasmBinary])
useEffect(() => {
setSendMessage(() => vm
? vm.send
: null)
return () => setSendMessage(null)
}, [vm])
const textWindow = (inbox) => (currentWindow) => {
const props = {
inbox,
currentWindow,
}
return ({
buffer: ,
grid: ,
})[currentWindow.type]
}
const byTop = (a, b) =>
a.top - b.top
return status.stage !== 'ready'
? ()
: (
{
windows
.sort(byTop)
.filter(singleWindow
? ({ id }) => id === currentWindowId
: () => true)
.map(textWindow(inbox))
}
)
}