import { h } from 'preact'
import { useState, useEffect } from 'preact/hooks'
import {
compressToUTF16 as encode,
decompressFromUTF16 as decode
} from 'lz-string'
import CheapGlkOte from 'cheap-glkote'
import TextBuffer from './TextBuffer'
import GridBuffer from './GridBuffer'
import InputBox from './InputBox'
import Status from './Status'
import './player.css'
const INITIAL_STATUS = {
stage: 'loading',
details: ['Preparing']
}
const runMachine = ({ engine: Engine, file, handlers }) => {
const vm = new Engine()
const { glkInterface, sendFn } = CheapGlkOte(handlers)
vm.prepare(file, glkInterface)
vm.start()
return { sendFn, instance: vm }
}
const Handlers = ({
setStatus,
setWindows,
setCurrentWindowId,
setInputType,
setInbox
}) => ({
onInit: _ => setStatus({ stage: 'ready' }),
/* */
onUpdateWindows: windows => {
setWindows(windows)
},
onUpdateInputs: ([{type, id}]) => {
setCurrentWindowId(id)
setInputType(type)
},
onUpdateContent: setInbox,
onDisable: _ => setInputType(null),
/* */
onFileNameRequest: (tosave, usage, _, setFileName) => {
setFileName({
usage,
filename: prompt('Enter the filename')
})
},
onFileRead: ({ filename }) => {
const content = localStorage.getItem(`fake-fs/${filename}`)
return decode(content)
},
onFileWrite: ({ filename }, content) => {
localStorage.setItem(`fake-fs/${filename}`, encode(content))
},
/* */
onExit: _ => setInputType(null)
})
export default function ({ vmParts: { file, engine } }) {
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 vm = runMachine({
engine,
file,
handlers: Handlers({
setStatus,
setWindows,
setCurrentWindowId,
setInputType,
setInbox
})
})
setVm(vm)
}, [file, engine])
useEffect(() => {
setSendMessage(_ => vm
? vm.sendFn
: null)
}, [vm])
const textWindow = inbox => currentWindow => {
const props = {
inbox,
currentWindow
}
return ({
'buffer': ,
'grid':
})[currentWindow.type]
}
return status.stage !== 'ready'
? ()
: (
{ windows
// .filter(({id}) => id === currentWindowId)
.map(textWindow(inbox)) }
)
}