import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Component } from 'react';
import { Layout, Modal, Empty, Typography } from 'antd';
import PrismCode from '../../PrismCode';
import { playgroundAction } from '../../events';
import { Menu, Tabs, Tree } from '../../components';
import { Alert, CubeLoader } from '../../atoms';
import { playgroundFetch } from '../../shared/helpers';
import { AppContext, AppContextConsumer } from '../../components/AppContext';
import { ButtonDropdown } from '../../QueryBuilder/ButtonDropdown';
import { SchemaFormat } from '../../types';
const { Content, Sider } = Layout;
const { TreeNode } = Tree;
const { TabPane } = Tabs;
const schemasMap = {};
const schemaToTreeData = (schemas) => Object.keys(schemas).map((schemaName) => ({
    title: schemaName,
    key: schemaName,
    treeData: Object.keys(schemas[schemaName]).map((tableName) => {
        const key = `${schemaName}.${tableName}`;
        schemasMap[key] = [schemaName, tableName];
        return {
            title: tableName,
            key,
        };
    }),
}));
export class SchemaPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            expandedKeys: [],
            autoExpandParent: true,
            checkedKeys: [],
            selectedKeys: [],
            activeTab: 'schema',
            files: [],
            isDocker: null,
            shown: false
        };
    }
    async componentDidMount() {
        await this.loadDBSchema();
        await this.loadFiles();
    }
    onExpand(expandedKeys) {
        playgroundAction('Expand Tables');
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    }
    onCheck(checkedKeys) {
        playgroundAction('Check Tables');
        this.setState({ checkedKeys });
    }
    onSelect(selectedKeys) {
        this.setState({ selectedKeys });
    }
    async loadDBSchema() {
        this.setState({ schemaLoading: true });
        try {
            const res = await playgroundFetch('playground/db-schema');
            const result = await res.json();
            this.setState({
                tablesSchema: result.tablesSchema,
            });
        }
        catch (e) {
            this.setState({ schemaLoadingError: e });
        }
        finally {
            this.setState({ schemaLoading: false });
        }
    }
    async loadFiles() {
        const res = await playgroundFetch('playground/files');
        const result = await res.json();
        this.setState({
            files: result.files,
            activeTab: result.files && result.files.length > 0 ? 'files' : 'schema',
        });
    }
    async generateSchema(format = SchemaFormat.js) {
        const { checkedKeys, tablesSchema } = this.state;
        const { history } = this.props;
        const options = { format };
        playgroundAction('Generate Schema', options);
        const res = await playgroundFetch('playground/generate-schema', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                format,
                tables: checkedKeys
                    .filter((k) => !!schemasMap[k])
                    .map((e) => schemasMap[e]),
                tablesSchema,
            }),
        });
        if (res.status === 200) {
            playgroundAction('Generate Schema Success', options);
            await this.loadFiles();
            this.setState({ checkedKeys: [], activeTab: 'files' });
            Modal.success({
                title: 'Data model files successfully generated!',
                content: 'You can start exploring your data model and building the charts',
                okText: 'Build',
                cancelText: 'Close',
                okCancel: true,
                onOk() {
                    history.push('/build');
                },
            });
        }
        else {
            playgroundAction('Generate Schema Fail', {
                error: await res.text(),
                ...options,
            });
        }
    }
    selectedFileContent() {
        const file = this.selectedFile();
        return file && file.content;
    }
    selectedFile() {
        const { files, selectedFile } = this.state;
        return files.find((f) => f.fileName === selectedFile);
    }
    renderFilesMenu() {
        const { selectedFile, files } = this.state;
        return (_jsx(Menu, { mode: "inline", onClick: ({ key }) => {
                playgroundAction('Select File');
                this.setState({ selectedFile: key });
            }, selectedKeys: selectedFile ? [selectedFile] : [], children: files.map((f) => (_jsx(Menu.Item, { children: f.fileName }, f.fileName))) }));
    }
    render() {
        const { schemaLoading, schemaLoadingError, tablesSchema, selectedFile, expandedKeys, autoExpandParent, checkedKeys, selectedKeys, activeTab, isDocker, } = this.state;
        const { playgroundContext } = this.context;
        const [major, minor] = playgroundContext.coreServerVersion
            ? playgroundContext.coreServerVersion.split('.')
            : [];
        const isYamlFormatSupported = (Number(major) > 0) || (!minor || Number(minor) >= 31);
        const renderTreeNodes = (data) => data.map((item) => {
            if (item.treeData) {
                return (
                // @ts-ignore
                _jsx(TreeNode, { title: item.title, dataRef: item, children: renderTreeNodes(item.treeData) }, item.key));
            }
            return _jsx(TreeNode, { ...item });
        });
        const renderTree = () => Object.keys(tablesSchema || {}).length > 0 ? (_jsx(Tree, { checkable: true, onExpand: this.onExpand.bind(this), expandedKeys: expandedKeys, autoExpandParent: autoExpandParent, onCheck: this.onCheck.bind(this), checkedKeys: checkedKeys, onSelect: this.onSelect.bind(this), selectedKeys: selectedKeys, children: renderTreeNodes(schemaToTreeData(tablesSchema || {})) })) : (_jsx(Alert, { message: "Empty DB Schema", description: "Please check connection settings", type: "warning" }));
        const renderTreeOrError = () => schemaLoadingError ? (_jsx(Alert, { "data-testid": "schema-error", message: "Error while loading DB schema", description: schemaLoadingError.toString(), type: "error" })) : (renderTree());
        return (_jsxs(Layout, { style: { height: '100%' }, children: [_jsx(Sider, { width: 340, className: "schema-sidebar", children: _jsxs(Tabs, { activeKey: activeTab, onChange: (tab) => this.setState({ activeTab: tab }), tabBarExtraContent: _jsx(ButtonDropdown, { show: this.state.shown, disabled: !checkedKeys.length, type: "primary", "data-testid": "chart-type-btn", overlay: _jsxs(Menu, { "data-testid": "generate-schema", children: [_jsx(Menu.Item, { title: !isYamlFormatSupported
                                            ? 'yaml schema format is supported by Cube 0.31.0 and later'
                                            : '', disabled: !isYamlFormatSupported, onClick: () => this.generateSchema(SchemaFormat.yaml), children: "YAML" }), _jsx(Menu.Item, { onClick: () => this.generateSchema(), children: "JavaScript" })] }), style: { border: 0 }, onOverlayOpen: () => this.setState({ shown: true }), onOverlayClose: () => this.setState({ shown: false }), onItemClick: () => this.setState({ shown: false }), children: "Generate Data Model" }), children: [_jsx(TabPane, { tab: "Tables", children: schemaLoading ? _jsx(CubeLoader, {}) : renderTreeOrError() }, "schema"), _jsx(TabPane, { tab: "Files", children: this.renderFilesMenu() }, "files")] }) }), _jsxs(Content, { style: {
                        minHeight: 280,
                        padding: 24,
                    }, children: [selectedFile && (_jsx(Alert, { message: isDocker ? (_jsxs("span", { children: ["Data model files are located and can be edited in the mount volume directory.", ' ', _jsx(Typography.Link, { href: "https://cube.dev/docs/data-modeling/overview", target: "_blank", children: "Learn more about working with Cube data model in the docs" })] })) : (_jsxs("span", { children: ["This file can be edited at\u00A0", _jsx("b", { children: this.selectedFile().absPath })] })), type: "info", style: { paddingTop: 10, paddingBottom: 11 } })), selectedFile ? (_jsx(PrismCode, { code: this.selectedFileContent(), style: {
                                padding: 0,
                                marginTop: 24,
                            } })) : (_jsx(Empty, { style: { marginTop: 50 }, description: "Select tables to generate Cube data model" })), _jsx(AppContextConsumer, { onReady: ({ playgroundContext }) => this.setState({ isDocker: playgroundContext?.isDocker }) })] })] }));
    }
}
SchemaPage.contextType = AppContext;
//# sourceMappingURL=SchemaPage.js.map