import { ResponseFieldError } from './request-error.js' import type { ScreenMode, ScreenPlan } from '../src/types/screen.js' import { integer, object, text } from './remote-state.js' const modes = [ 'UNSPECIFIED', 'COVER', 'INTRO', 'INTRO_DONE', 'CONCLUSION', 'CONCLUSION_DONE', 'RESULTS', 'TIMER', 'TEXT', ] export function parsePlan(value: unknown): ScreenPlan { const plan = value == null ? {} : object(value, 'plan') const list = plan.steps ?? [] if (!Array.isArray(list)) throw new ResponseFieldError('plan.steps', 'массив', list, 'Некорректные шаги плана') const steps = list.map((value, index) => { const field = `plan.steps[${index}]` const step = object(value, field) let mode: ScreenMode try { mode = integer( typeof step.mode === 'string' && step.mode.startsWith('SCREEN_MODE_') ? modes.indexOf(step.mode.slice(12)) : step.mode, 1, 8, `${field}.mode`, ) as ScreenMode } catch { throw new ResponseFieldError( `${field}.mode`, 'режим экрана 1–8 или enum ScreenMode', step.mode, 'Некорректный режим экрана', ) } const content = text(step.text ?? '', `${field}.text`).trim() const label = text(step.timerLabel ?? '', `${field}.timerLabel`).trim() const seconds = integer( step.timerDurationSeconds ?? 0, 0, 86400, `${field}.timerDurationSeconds`, ) if (mode === 8 && (!content || Buffer.byteLength(content) > 10000)) throw new ResponseFieldError( `${field}.text`, 'строка от 1 до 10000 байт', step.text, 'Текст шага должен содержать от 1 до 10000 байт', ) if (mode === 7 && (!seconds || Buffer.byteLength(label) > 200)) throw new ResponseFieldError( !seconds ? `${field}.timerDurationSeconds` : `${field}.timerLabel`, !seconds ? 'число от 1 до 86400' : 'строка до 200 байт', !seconds ? step.timerDurationSeconds : step.timerLabel, 'Укажите таймер от 1 до 86400 секунд и подпись до 200 байт', ) return { mode, text: content, timerLabel: mode === 7 ? label || 'Перерыв' : label, timerDurationSeconds: seconds, } }) return { steps, currentStep: integer( plan.currentStep ?? 0, 0, Math.max(0, steps.length - 1), 'plan.currentStep', ), } }