// Dependencies
import { designs as collectionDesigns } from '@freesewing/collection'
import { capitalize, hasRequiredMeasurements } from '@freesewing/utils'
import { initialEditorState } from './lib/index.mjs'
import { mergeConfig } from './config/index.mjs'
// Hooks
import React, { useState, useEffect } from 'react'
import { useEditorState } from './hooks/useEditorState.mjs'
// Components
import { View, viewLabels } from './components/views/index.mjs'
import { Spinner } from '@freesewing/react/components/Spinner'
import { AsideViewMenu } from './components/AsideViewMenu.mjs'
import { LoadingStatus } from './components/LoadingStatus.mjs'
import { ModalContextProvider } from '@freesewing/react/context/Modal'
import { LoadingStatusContextProvider } from '@freesewing/react/context/LoadingStatus'
import { useAccount } from '../../hooks/useAccount/index.mjs'
/**
* FreeSewing's pattern editor
*
* Editor is the high-level FreeSewing component
* that provides the entire pattern editing environment.
* This is a high-level wrapper that figures out what view to load initially,
* and handles state for the pattern, including the view.
*
* @component
* @param {object} props - All React props
* @param {object} [props.config = {}] - A configuration object for the editor
* @param {object} [props.design = false] - A design name to preset the editor to use this design
* @param {object} [props.preload = {}] - Any state to preload
* @param {function} [props.setTitle = false] - A way to set the page title
* @param {object} [props.localDesigns = {}] - A way to add local designs to the editor
* @param {function} [props.measurementsHelpProvider = false] - A function that should return to a URL for measurements help
*/
export const Editor = ({
config = {},
design = false,
preload = {},
setTitle = false,
localDesigns = {},
measurementHelpProvider = false,
}) => {
/*
* Bundle all designs
*/
const designs = { ...collectionDesigns, ...localDesigns }
/*
* Ephemeral state will not be stored in the state backend
* It is used for things like loading state and so on
*/
const [ephemeralState, setEphemeralState] = useState({})
/*
* Merge custom and default configuration
*/
const editorConfig = mergeConfig(config)
/*
* The Editor state is kept in a state backend (URL)
*/
const allState = useEditorState(
initialEditorState(preload, config),
setEphemeralState,
editorConfig
)
const state = allState[0]
const update = allState[2]
/*
* If state is not loaded, we return early
* However, we cannot return before the useEffect call and we need
* the view in the useEffect call which depends on state.
* So, if state is not ready, we make sure view is set to false and
* then return right after the useEffect code
*/
const [view, extraProps] = state
? viewfinder({ design, designs, preload, state, config: editorConfig })
: [false, {}]
/*
* Title is typically kept in state by the parent component
* so we should not call it inside the regular render but
* in the useEffect hook instead
*/
useEffect(() => {
if (typeof setTitle === 'function' && state.design) {
setTitle(`${capitalize(state.design)}${viewLabels[view] ? ' | ' + viewLabels[view].t : ''}`)
}
}, [setTitle, state.design, view])
/*
* Don't bother before state is initialized
*/
if (!state) return