"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
exports.ToggleColorModeButton = exports.Couple = exports.ExperimentPage = void 0;
// @jsx jsx
var core_1 = require("@chakra-ui/core");
var core_2 = require("@emotion/core");
var assign_1 = __importDefault(require("lodash/assign"));
var react_1 = __importStar(require("react"));
var fa_1 = require("react-icons/fa");
var fi_1 = require("react-icons/fi");
var md_1 = require("react-icons/md");
var react_is_1 = require("react-is");
var support_1 = require("../support");
var ClickToSource_1 = require("./ClickToSource");
var DefaultWrapper_1 = require("./DefaultWrapper");
var MarkdownStyler_1 = require("./MarkdownStyler");
var MobileNav_1 = require("./MobileNav");
core_2.jsx;
var mdxComponentPrefix = '_VitroMdx';
function ExperimentPage(_a) {
    var _b;
    var experimentsTree = _a.experimentsTree, GlobalWrapper = _a.GlobalWrapper, sourceExperimentPath = _a.sourceExperimentPath, _c = _a.fileExports, getFileExports = _c === void 0 ? function () { return Promise.resolve({}); } : _c;
    var _d = core_1.useColorMode(), colorMode = _d.colorMode, toggleColorMode = _d.toggleColorMode;
    var _e = react_1.useState(false), cssDebugEnabled = _e[0], setCssDebug = _e[1];
    var fileExportsObject = support_1.usePromise(getFileExports, {})[0];
    // let [fileExports] = usePromise(fileExportsImporter)
    var experimentComponents = react_1.useMemo(function () {
        return assign_1["default"].apply(void 0, __spreadArrays([{}], Object.keys(fileExportsObject)
            .filter(function (k) { return react_is_1.isValidElementType(fileExportsObject[k]); })
            .map(function (k) {
            var _a;
            return (_a = {}, _a[k] = fileExportsObject[k], _a);
        })));
    }, [fileExportsObject]);
    var ValidGlobalWrapper = react_1.useMemo(function () {
        return !GlobalWrapper || !react_is_1.isValidElementType(GlobalWrapper)
            ? DefaultWrapper_1.DefaultWrapper
            : GlobalWrapper;
    }, [GlobalWrapper, colorMode]);
    react_1.useEffect(function () {
        if (GlobalWrapper && !react_is_1.isValidElementType(GlobalWrapper)) {
            console.warn("your global wrapper is not a valid react component: " +
                String(GlobalWrapper));
        }
    }, [GlobalWrapper]);
    var _f = react_1.useState(''), clickToSeeSourceProvider = _f[0], setClickToSeeSource = _f[1];
    var vscodeUrl = "vscode://file" + sourceExperimentPath;
    // exported.then(z => console.log(Object.keys(z)))
    // console.log({ fileExports })
    var ExperimentWrapper = react_1.useMemo(function () {
        var _a;
        var experimentWrapper = (_a = fileExportsObject === null || fileExportsObject === void 0 ? void 0 : fileExportsObject["default"]) === null || _a === void 0 ? void 0 : _a.wrapper;
        if (experimentWrapper) {
            console.info('using experiments wrapper ' + (experimentWrapper === null || experimentWrapper === void 0 ? void 0 : experimentWrapper.name));
        }
        return experimentWrapper || DefaultWrapper_1.DefaultWrapper;
    }, [fileExportsObject, colorMode]);
    var experimentTitle = ((_b = fileExportsObject === null || fileExportsObject === void 0 ? void 0 : fileExportsObject["default"]) === null || _b === void 0 ? void 0 : _b.title) ||
        support_1.formatPathToTitle(sourceExperimentPath) ||
        'Untitled';
    var bg = react_1.useMemo(function () { return ({ light: 'white', dark: 'gray.700' }[colorMode]); }, [colorMode]);
    // if (!exported || !story || !storyObject) {
    //     // TODO return 404
    //     return null
    // }
    support_1.debug({ ValidGlobalWrapper: ValidGlobalWrapper, ExperimentWrapper: ExperimentWrapper });
    return (react_1["default"].createElement(core_1.Stack, { spacing: '10' },
        react_1["default"].createElement(core_1.Stack, { flexShrink: 0, align: 'flex-start', spacing: '4' },
            react_1["default"].createElement(core_1.Stack, { height: support_1.TOP_TITLE_H, spacing: '3', align: 'flex-end', direction: 'row', width: '100%' },
                react_1["default"].createElement(core_1.Box, { fontSize: '32px', minWidth: '0', width: 'auto', isTruncated: true, fontWeight: 'medium' }, experimentTitle),
                react_1["default"].createElement(core_1.Box, { flex: '1' }),
                react_1["default"].createElement(exports.ToggleColorModeButton, { mr: ['0px', null, null, '-10px !important'] }),
                react_1["default"].createElement(MobileNav_1.MobileNav, { display: ['flex', null, null, 'none'], experimentsTree: experimentsTree })),
            process.env.NODE_ENV == 'development' && (react_1["default"].createElement(core_1.Link, { as: 'a', fontWeight: '500', href: vscodeUrl, opacity: 0.7 },
                react_1["default"].createElement(core_1.Box, { d: 'inline', size: '.8em', mr: '3', as: fa_1.FaLink }),
                "Open in vscode"))),
        react_1["default"].createElement(core_1.Stack, { align: 'center', flexShrink: 0, direction: 'row' },
            react_1["default"].createElement(core_1.Box, { flex: '1' }),
            react_1["default"].createElement(core_1.Button, { onClick: function () { return setCssDebug(function (x) { return !x; }); }, opacity: 0.8, bg: bg, w: 'auto' },
                react_1["default"].createElement(core_1.Box, { mr: '2', d: 'inline-block', as: fa_1.FaBug }),
                "CSS debug"),
            react_1["default"].createElement(core_1.Select, { onChange: function (e) {
                    var value = e.target.value;
                    setClickToSeeSource(value);
                }, fontWeight: 500, value: clickToSeeSourceProvider, opacity: 0.8, variant: 'filled', bg: bg, 
                // placeholder='click to see source'
                w: 'auto' },
                react_1["default"].createElement("option", { value: '', children: 'click to source disabled' }),
                react_1["default"].createElement("option", { value: 'vscode', children: 'click to source on Vscode' }))),
        react_1["default"].createElement(core_1.Stack, { flexShrink: 0, 
            // direction='row'
            flexWrap: 'wrap', overflow: 'visible' // TODO simple grid has overflow hidden
            , 
            // justify='space-between'
            spacing: '16' }, experimentComponents &&
            Object.keys(experimentComponents)
                .filter(function (k) { return k !== 'default'; })
                .map(function (k) {
                var Component = experimentComponents[k];
                // console.log({ Component })
                if (!react_is_1.isValidElementType(Component)) {
                    return null;
                }
                if (k.startsWith(mdxComponentPrefix)) {
                    return (react_1["default"].createElement(MarkdownStyler_1.MdxStyler, null,
                        react_1["default"].createElement(Component, null)));
                }
                var id = sourceExperimentPath + "/" + k;
                return (react_1["default"].createElement(StoryBlock, { maxW: '100%', overflowX: 'auto' // TODO overflow x scroll not working
                    , flexShrink: 0, title: k, blockWidth: '100%', key: id, id: id },
                    react_1["default"].createElement(ClickToSource_1.ClickToSourceProviderStateless, { value: {
                            provider: clickToSeeSourceProvider
                        }, onChange: function (state) {
                            setClickToSeeSource(state.provider);
                        } },
                        react_1["default"].createElement(core_1.Stack
                        // flex='1'
                        , { 
                            // flex='1'
                            w: '100%', h: '100%', minH: '100%', spacing: '0', align: 'center', justify: 'center', className: cssDebugEnabled
                                ? 'vitro-inspect-css'
                                : '' },
                            react_1["default"].createElement(ValidGlobalWrapper, { key: colorMode, dark: colorMode == 'dark' },
                                react_1["default"].createElement(ExperimentWrapper, { key: colorMode, dark: colorMode == 'dark' },
                                    react_1["default"].createElement(Component, { key: colorMode, dark: colorMode == 'dark' })))))));
            }))));
}
exports.ExperimentPage = ExperimentPage;
var StoryBlock = function (_a) {
    var children = _a.children, blockWidth = _a.blockWidth, id = _a.id, title = _a.title, rest = __rest(_a, ["children", "blockWidth", "id", "title"]);
    var _b = react_1.useState(false), fullScreen = _b[0], setFullScreen = _b[1];
    var colorMode = core_1.useColorMode().colorMode;
    var bg = react_1.useMemo(function () { return ({ light: 'white', dark: 'gray.700' }[colorMode]); }, [colorMode]);
    var fullScreenStyles = react_1.useMemo(function () { return ({
        w: '100vw',
        maxW: '100vw',
        h: '100vh',
        p: '50px',
        pt: '80px',
        bg: bg,
        position: 'fixed',
        overflow: 'auto',
        top: '0',
        left: '0',
        right: '0',
        bottom: '0',
        zIndex: 100000
    }); }, [bg]);
    react_1.useEffect(function () {
        if (!react_1.Profiler) {
            console.warn('your current react version does not export `Profiler`, some features are disabled');
        }
    }, []);
    var actualDurationRef = react_1.useRef('0.00ms');
    var renderCount = react_1.useRef(0);
    // renderCount.current = 0
    // console.log({ id })
    var profile = react_1.useCallback(function (id, _, actualDuration) {
        // console.log({ id, actualDuration })
        renderCount.current++;
        actualDurationRef.current = actualDuration.toFixed(2) + 'ms';
    }, []);
    return (react_1["default"].createElement(core_1.Stack, __assign({ spacing: '3', flexShrink: 0, flexGrow: 0, minHeight: '340px', 
        // minW='100px'
        // overflowX='hidden'
        overflow: 'visible', flexBasis: blockWidth, position: 'relative' }, rest, (fullScreen ? fullScreenStyles : {})),
        react_1["default"].createElement(core_1.Box
        // spacing='0'
        , { 
            // spacing='0'
            flexShrink: 0, flex: '1', minH: '340px', minHeight: '340px' },
            react_1["default"].createElement(core_1.Stack, { minH: '340px', shadow: 'sm', 
                // shadow='0 0 40px rgba(0,0,0,0.1), 0 -10px 40px rgba(0,0,0,0.1)'
                // borderWidth='1px'
                flex: '1', 
                // shadow='sm'
                borderRadius: '10px', overflow: 'hidden', overflowX: 'auto', bg: bg, 
                // minH='100%'
                spacing: '0', align: 'center', justify: 'center' },
                react_1["default"].createElement(ErrorBoundary, null, react_1.Profiler ? (react_1["default"].createElement(react_1.Profiler, { id: id, onRender: profile }, children)) : (children)))),
        react_1["default"].createElement(core_1.Stack, { zIndex: 700, spacing: '8', position: 'absolute', opacity: 0.7, top: fullScreen ? '20px' : '10px', left: fullScreen ? '20px' : '20px', right: fullScreen ? '20px' : '20px', direction: 'row', align: 'center' },
            react_1["default"].createElement(core_1.Box, { borderRadius: 'md', bg: bg, p: '4px', fontSize: '18px', fontWeight: 'medium' }, title),
            react_1["default"].createElement(core_1.Box, { flex: '1' }),
            react_1["default"].createElement(exports.Couple, { borderRadius: 'md', bg: bg, p: '4px', a: react_1["default"].createElement(core_1.Box, { as: fi_1.FiZap, size: '1em' }), b: react_1["default"].createElement(AutoUpdateBox, { fontWeight: '500', contentRef: actualDurationRef }) }),
            ")",
            react_1["default"].createElement(exports.Couple, { borderRadius: 'md', bg: bg, p: '4px', a: react_1["default"].createElement(core_1.Box, { as: fi_1.FiHash, size: '1em' }), b: react_1["default"].createElement(AutoUpdateBox, { fontWeight: '500', map: function (x) { return x + ' renders'; }, contentRef: renderCount }) }),
            ")",
            react_1["default"].createElement(core_1.IconButton, { borderRadius: 'md', bg: bg, 
                // isRound
                size: 'sm', onClick: function () { return setFullScreen(function (x) { return !x; }); }, fontSize: '1.4em', 
                // bg='transparent'
                icon: fullScreen ? md_1.MdFullscreenExit : md_1.MdFullscreen, "aria-label": 'full-screen' }))));
};
var AutoUpdateBox = function (_a) {
    var _b = _a.after, after = _b === void 0 ? 1000 : _b, map = _a.map, contentRef = _a.contentRef, rest = __rest(_a, ["after", "map", "contentRef"]);
    var _c = react_1.useState(null), _ = _c[0], render = _c[1];
    react_1.useEffect(function () {
        var id = setInterval(function () {
            render('');
        }, after);
        return function () { return clearInterval(id); };
    }, []);
    return (react_1["default"].createElement(core_1.Box, __assign({}, rest, { children: map ? map(contentRef.current) : contentRef.current })));
};
var ErrorBoundary = /** @class */ (function (_super) {
    __extends(ErrorBoundary, _super);
    function ErrorBoundary() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = { hasError: false, message: '', trace: '', traceOpen: false };
        return _this;
    }
    ErrorBoundary.getDerivedStateFromError = function (error, info) {
        // Update state so the next render will show the fallback UI.
        return {
            hasError: true,
            message: (error === null || error === void 0 ? void 0 : error.message) || 'no error message found',
            trace: error === null || error === void 0 ? void 0 : error.stack
        };
    };
    ErrorBoundary.prototype.componentDidCatch = function (error, errorInfo) {
        // You can also log the error to an error reporting service
        console.error(error, errorInfo);
    };
    ErrorBoundary.prototype.render = function () {
        var _this = this;
        var _a = this.state, hasError = _a.hasError, message = _a.message, trace = _a.trace, traceOpen = _a.traceOpen;
        if (hasError) {
            // You can render any custom fallback UI
            return (react_1["default"].createElement(core_1.Stack, { m: '20', fontWeight: '500', align: 'center', justify: 'center', color: 'red.500', spacing: '6', maxW: '100%' },
                react_1["default"].createElement(core_1.Stack, { align: 'center', spacing: '2' },
                    react_1["default"].createElement(core_1.Box, { fontWeight: 'bold', textAlign: 'center', display: 'inline-block' }, "Error"),
                    react_1["default"].createElement(core_1.Box, { textAlign: 'center', display: 'inline-block' }, message),
                    react_1["default"].createElement(core_1.Button, { display: 'inline-block', size: 'sm', variant: 'ghost', onClick: function () {
                            return _this.setState(function (x) { return (__assign(__assign({}, x), { traceOpen: !x.traceOpen })); });
                        } }, "see trace")),
                react_1["default"].createElement(core_1.Collapse, { overflowX: 'auto', isOpen: traceOpen },
                    react_1["default"].createElement(core_1.Box, { fontSize: '0.9em', as: 'pre' }, trace))));
        }
        return this.props.children;
    };
    return ErrorBoundary;
}(react_1["default"].Component));
exports.Couple = function (_a) {
    var a = _a.a, b = _a.b, _b = _a.hide, hide = _b === void 0 ? false : _b, rest = __rest(_a, ["a", "b", "hide"]);
    return (react_1["default"].createElement(core_1.Stack
    // display={hide ? 'none' : ['none', null, 'flex']}
    , __assign({ 
        // display={hide ? 'none' : ['none', null, 'flex']}
        isTruncated: true, direction: 'row', align: 'center', spacing: '1' }, rest),
        react_1["default"].createElement(core_1.Box, null, a),
        react_1["default"].createElement(core_1.Box, null, b)));
};
exports.ToggleColorModeButton = function (_a) {
    var rest = __rest(_a, []);
    var _b = core_1.useColorMode(), colorMode = _b.colorMode, toggleColorMode = _b.toggleColorMode;
    return (react_1["default"].createElement(core_1.IconButton
    // bg={{ light: 'white', dark: 'gray.700' }[colorMode]}
    // size='sm'
    // shadow='sm'
    , __assign({ 
        // bg={{ light: 'white', dark: 'gray.700' }[colorMode]}
        // size='sm'
        // shadow='sm'
        onClick: toggleColorMode, fontSize: '1.2em', "aria-label": 'color-mode-toggle', icon: colorMode === 'dark' ? 'moon' : 'sun' }, rest)));
};
//# sourceMappingURL=ExperimentPage.js.map