import React from 'react';
import { Expandable } from '@workday/canvas-kit-labs-react/expandable';
import { defaultJSDoc } from '../../docgen/docParser';
import { MDX } from '../MDXElements';
import { SymbolDoc } from '../SymbolDoc';
import { PropertiesTable, registerWidget, Value } from '../Value';
import { Heading, HeadingLevelContext, SymbolDialog } from '../widgetUtils';
var 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
 * }
 * ```
 */
var ParentComponentJSDocContext = React.createContext(defaultJSDoc);
var fileNameToCategoryMap = {
    Layout: [
        'utils/layout',
        'utils/gridArea',
        'utils/gridItem',
        'utils/flexItem',
        'utils/position',
        'utils/space',
        'utils/stack',
    ],
    Color: ['utils/color', 'utils/background'],
    Border: ['utils/border'],
    Depth: ['utils/depth'],
    Text: ['utils/text'],
    Other: ['utils/other'],
};
registerWidget('enhancedComponent', function (_a) {
    var value = _a.value, doc = _a.doc, meta = _a.meta;
    var groups = groupProps(value.props);
    var parentComponentName = React.useContext(ParentComponentNameContext);
    var 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 (React.createElement(React.Fragment, null,
            React.createElement(MDX, { as: "p" },
                "This component references the",
                ' ',
                React.createElement(ParentComponentNameContext.Provider, { value: "" },
                    React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
                        React.createElement(SymbolDialog, { value: { kind: 'symbol', name: value.displayName || '' } }))),
                ' ',
                "component.")));
    }
    return (React.createElement(React.Fragment, null,
        value.styleComponent ? (React.createElement(React.Fragment, null,
            React.createElement(Heading, { headingOffset: 1 }, "Layout Component"),
            React.createElement(MDX, { as: "p" },
                React.createElement("code", null, value.displayName),
                " supports all props from the",
                React.createElement("code", null,
                    React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
                        React.createElement(SymbolDialog, { value: value.styleComponent }))),
                "layout component."))) : null,
        React.createElement(Heading, { headingOffset: 1 }, "Props"),
        value.baseElement && (React.createElement(ParentComponentJSDocContext.Provider, { value: defaultJSDoc },
            React.createElement(MDX, { as: "p" },
                "Props extend from ",
                React.createElement(Value, { value: value.baseElement }),
                ". Changing the ",
                React.createElement("code", null, "as"),
                " prop will change the element interface."))),
        value.componentType === 'container' && value.model ? (React.createElement(MDX, { as: "p" },
            "Props extend from ",
            React.createElement(SymbolDialog, { value: { kind: 'symbol', name: value.model + "Config" } }),
            ". If a ",
            React.createElement("code", null, "model"),
            " is passed, props from ",
            React.createElement("code", null,
                value.model,
                "Config"),
            " are ignored.")) : null,
        Object.keys(groups).map(function (key) {
            return (React.createElement(React.Fragment, { key: key }, key === 'Local' ? (React.createElement(PropertiesTable, { properties: groups[key] })) : (React.createElement(Expandable, null,
                React.createElement(Expandable.Target, { headingLevel: "h5" },
                    React.createElement(Expandable.Title, null, key),
                    React.createElement(Expandable.Icon, { iconPosition: "end" })),
                React.createElement(Expandable.Content, null,
                    React.createElement(PropertiesTable, { properties: groups[key] }))))));
        }),
        value.elemPropsHook ? (React.createElement(SymbolDoc, { name: value.elemPropsHook, headingStart: headingLevel + 1 })) : null,
        value.subComponents
            ? value.subComponents.map(function (c, i) {
                return (React.createElement(React.Fragment, { key: i },
                    React.createElement(Heading, null,
                        parentComponentName ? parentComponentName : value.displayName,
                        ".",
                        c.name),
                    React.createElement(ParentComponentNameContext.Provider, { value: (parentComponentName ? parentComponentName : value.displayName) + "." + c.name },
                        React.createElement(ParentComponentJSDocContext.Provider, { value: c },
                            React.createElement(SymbolDoc, { name: c.symbol, hideHeading: true, descriptionOverride: c.description })))));
            })
            : null,
        value.componentType === 'container' && value.model ? (React.createElement(React.Fragment, null,
            React.createElement(Heading, { headingOffset: -1 }, "Model"),
            React.createElement(SymbolDoc, { name: "use" + value.model }))) : null));
});
function groupProps(props) {
    var categories = { Local: [] };
    for (var key in fileNameToCategoryMap) {
        categories[key] = [];
    }
    var _loop_1 = function (prop) {
        var found = false;
        for (var key in fileNameToCategoryMap) {
            if (fileNameToCategoryMap[key].find(function (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);
        }
    };
    for (var _i = 0, props_1 = props; _i < props_1.length; _i++) {
        var prop = props_1[_i];
        _loop_1(prop);
    }
    // clear out categories that don't have anything in them
    return Object.keys(categories).reduce(function (result, key) {
        if (categories[key].length) {
            result[key] = categories[key];
        }
        return result;
    }, {});
}
