import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from 'react';
import { Expandable } from '@workday/canvas-kit-react/expandable';
import { defaultJSDoc } from '../../docgen/docParser';
import { MDX } from '../MDXElements';
import { SymbolDoc } from '../SymbolDoc';
import { PropertiesTable, Value, registerWidget } from '../Value';
import { Heading, HeadingLevelContext, SymbolDialog } from '../widgetUtils';
const ParentComponentNameContext = React.createContext('');
/**
 * Used to keep track of JSDoc in subcomponent definitions.
 *
 * For example:
 * ```tsx
 * subComponents: {
 *   // JSDoc goes here instead of on `TabsItem` for better dev experience
 *   Item: TabsItem
 * }
 * ```
 */
const ParentComponentJSDocContext = React.createContext(defaultJSDoc);
const fileNameToCategoryMap = {
    Layout: [
        'utils/layout',
        'utils/gridArea',
        'utils/gridItem',
        'utils/flexItem',
        'utils/position',
        'utils/space',
    ],
    Color: ['utils/color', 'utils/background'],
    Border: ['utils/border'],
    Depth: ['utils/depth'],
    Text: ['utils/text'],
    Other: ['utils/other'],
};
registerWidget('enhancedComponent', ({ value, doc, meta }) => {
    var _a, _b, _c;
    const groups = groupProps(value.props);
    const parentComponentName = React.useContext(ParentComponentNameContext);
    const headingLevel = React.useContext(HeadingLevelContext);
    // We don't want to re-document a subcomponent that is a container component with a different
    // model. If we detect another container, only render the intro and a link to the container
    // component
    if (parentComponentName && value.componentType === 'container') {
        return (_jsx(_Fragment, { children: _jsxs(MDX, { as: "p", children: ["This component references the", ' ', _jsx(ParentComponentNameContext.Provider, { value: "", children: _jsx(ParentComponentJSDocContext.Provider, { value: defaultJSDoc, children: _jsx(SymbolDialog, { value: { kind: 'symbol', name: value.displayName || '' } }) }) }), ' ', "component."] }) }));
    }
    return (_jsxs(_Fragment, { children: [value.styleComponent ? (_jsxs(_Fragment, { children: [_jsx(Heading, { headingOffset: 1, id: parentComponentName
                            ? `${parentComponentName.toLowerCase()}-layout-component-api`
                            : `${(_a = value.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()}-layout-component-api`, children: "Layout Component" }), _jsxs(MDX, { as: "p", children: [_jsx("code", { children: value.displayName || parentComponentName }), " supports all props from the", _jsx("code", { children: _jsx(ParentComponentJSDocContext.Provider, { value: defaultJSDoc, children: _jsx(SymbolDialog, { value: value.styleComponent }) }) }), "layout component."] })] })) : null, _jsx(Heading, { headingOffset: 1, id: parentComponentName
                    ? `${parentComponentName.toLowerCase()}-props-api`
                    : `${(_b = value.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()}-props-api`, children: "Props" }), value.baseElement && (_jsx(ParentComponentJSDocContext.Provider, { value: defaultJSDoc, children: _jsxs(MDX, { as: "p", children: ["Props extend from ", _jsx(Value, { value: value.baseElement }), ". Changing the ", _jsx("code", { children: "as" }), " prop will change the element interface."] }) })), value.componentType === 'container' && value.model ? (_jsxs(MDX, { as: "p", children: ["Props extend from ", _jsx(SymbolDialog, { value: { kind: 'symbol', name: `${value.model}Config` } }), ". If a ", _jsx("code", { children: "model" }), " is passed, props from ", _jsxs("code", { children: [value.model, "Config"] }), " are ignored."] })) : null, Object.keys(groups).map(key => {
                return (_jsx(React.Fragment, { children: key === 'Local' ? (_jsx(PropertiesTable, { properties: groups[key] })) : (_jsxs(Expandable, { children: [_jsxs(Expandable.Target, { headingLevel: "h5", children: [_jsx(Expandable.Title, { children: key }), _jsx(Expandable.Icon, { iconPosition: "end" })] }), _jsx(Expandable.Content, { children: _jsx(PropertiesTable, { properties: groups[key] }) })] })) }, key));
            }), value.elemPropsHook ? (_jsx(SymbolDoc, { name: value.elemPropsHook, headingStart: headingLevel + 1 })) : null, value.subComponents
                ? value.subComponents.map((c, i) => {
                    var _a;
                    return (_jsxs(React.Fragment, { children: [_jsxs(Heading, { id: `${(_a = value.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()}.${c.name.toLowerCase()}-api`, children: [parentComponentName ? parentComponentName : value.displayName, ".", c.name] }), _jsx(ParentComponentNameContext.Provider, { value: `${parentComponentName ? parentComponentName : value.displayName}.${c.name}`, children: _jsx(ParentComponentJSDocContext.Provider, { value: c, children: _jsx(SymbolDoc, { name: c.symbol, fileName: c.declarations[c.declarations.length - 1].filePath, hideHeading: true, descriptionOverride: c.description }) }) })] }, i));
                })
                : null, value.componentType === 'container' && value.model ? (_jsxs(_Fragment, { children: [_jsx(Heading, { id: `${(_c = value.displayName) === null || _c === void 0 ? void 0 : _c.toLowerCase()}-model-api`, headingOffset: -1, children: "Model" }), _jsx(SymbolDoc, { name: `use${value.model}` })] })) : null] }));
});
function groupProps(props) {
    const categories = { Local: [] };
    // eslint-disable-next-line guard-for-in
    for (const key in fileNameToCategoryMap) {
        categories[key] = [];
    }
    for (const prop of props) {
        let found = false;
        for (const key in fileNameToCategoryMap) {
            if (fileNameToCategoryMap[key].find(match => { var _a; return (_a = prop.declarations[0]) === null || _a === void 0 ? void 0 : _a.filePath.includes(match); })) {
                found = true;
                categories[key].push(prop);
            }
        }
        if (!found) {
            categories.Local.push(prop);
        }
    }
    // clear out categories that don't have anything in them
    return Object.keys(categories).reduce((result, key) => {
        if (categories[key].length) {
            result[key] = categories[key];
        }
        return result;
    }, {});
}
