import { Maybe, doesExist, mustDefault, mustExist } from '@apextoaster/js-utils';
import { Alert, Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Divider, MenuItem, Stack, Switch, TextField } from '@mui/material';
import React from 'react';
import { useStore } from 'zustand';
import { World, NumberParameter, StringParameter, Parameter, Action } from './models';
import { StoreState, store } from './store';
// region parameter components
export interface BooleanParameterProps {
name: string;
setParameter: (value: boolean) => void;
}
export function BooleanParameter(props: BooleanParameterProps) {
return ;
}
export function EnumParameterItem(props: NumberParameterProps | StringParameterProps) {
const { name, parameter, setParameter } = props;
const enumValues = mustExist(parameter.enum);
const defaultValue = mustDefault(parameter.default, enumValues[0]);
return setParameter(event.target.value)}
>
{enumValues.map((value) => )}
;
}
export interface NumberParameterProps {
name: string;
parameter: NumberParameter;
setParameter: (value: number) => void;
}
export function NumberParameterItem(props: NumberParameterProps) {
const { name, parameter, setParameter } = props;
if (doesExist(parameter.enum)) {
return ;
}
return setParameter(parseFloat(event.target.value))}
/>;
}
export interface StringParameterProps {
name: string;
parameter: StringParameter;
setParameter: (value: string) => void;
}
export function StringParameterItem(props: StringParameterProps) {
const { name, parameter, setParameter } = props;
if (doesExist(parameter.enum)) {
return ;
}
return setParameter(event.target.value)}
/>;
}
export interface UnknownParameterProps {
name: string;
}
export function UnknownParameter(props: UnknownParameterProps) {
const { name } = props;
return Unknown parameter type: {name};
}
// endregion
export const SIGNIFICANT_PARAMETERS = ['character', 'direction', 'item', 'room', 'target'];
export function listCharacters(world: World) {
return world.rooms.flatMap((room) => room.characters);
}
export function listItems(world: World) {
return world.rooms.flatMap((room) => room.items);
}
export function listPortals(world: World) {
return world.rooms.flatMap((room) => room.portals);
}
export function enumerateSignificantParameterValues(name: string, world: World) {
switch (name) {
case 'character':
return listCharacters(world).map((character) => character.name);
case 'direction':
return listPortals(world).map((portal) => portal.name);
case 'item':
return listItems(world).map((item) => item.name);
case 'room':
return world.rooms.map((room) => room.name);
case 'target':
{
const characters = listCharacters(world);
const items = listItems(world);
return [
...characters.map((character) => character.name),
...items.map((item) => item.name),
];
}
default:
return [];
}
}
export function convertSignificantParameter(name: string, parameter: Parameter, world: Maybe): Parameter {
if (doesExist(world) && SIGNIFICANT_PARAMETERS.includes(name)) {
return {
...parameter,
enum: enumerateSignificantParameterValues(name, world),
};
}
return parameter;
}
export function selectWorld(state: StoreState) {
return {
world: state.world,
};
}
export function formatAction(action: string, parameters: Record) {
return `~${action}:${Object.entries(parameters).map(([name, value]) => `${name}=${value}`).join(',')}`;
}
export interface PromptActionProps {
action: Action;
setAction: (action: string) => void;
}
export function PromptAction(props: PromptActionProps) {
const { action, setAction } = props;
const { world } = useStore(store, selectWorld);
const [parameterValues, setParameterValues] = React.useState>({});
// create an input for each parameter
const inputs = Object.entries(action.function.parameters.properties).map(([name, parameter]) => {
const convertedParameter = convertSignificantParameter(name, parameter, world);
switch (convertedParameter.type) {
case 'string':
return {
setParameterValues((old) => ({ ...old, [name]: value }));
}} />;
case 'number':
return {
setParameterValues((old) => ({ ...old, [name]: value }));
}} />;
default:
return ;
}
});
return
{inputs}
;
}
export function selectPromptEvent(state: StoreState) {
return {
promptEvent: state.promptEvent,
};
}
export interface PromptDialogProps {
sendInput: (input: string) => void;
skipPrompt: () => void;
}
export function PromptDialog(props: PromptDialogProps) {
const { sendInput, skipPrompt } = props;
const { promptEvent } = useStore(store, selectPromptEvent);
const [input, setInput] = React.useState('');
// eslint-disable-next-line no-restricted-syntax
if (!doesExist(promptEvent)) {
return ;
}
return ;
}