import { jsx, jsxs, Fragment } from "react/jsx-runtime";

import { Typography, Stepper, Step, StepLabel, StepContent, CircularProgress, Alert, AlertTitle, FormControl, TextField, FormLabel, RadioGroup, FormControlLabel, Radio, Switch, Button } from "@mui/material";

import StackBlitzSDK from "@stackblitz/sdk";

import { load } from "js-yaml";

import React from "react";

import { NestiaMigrateApplication } from "@nestia/migrate";

import * as jsDoc from "prettier-plugin-jsdoc";

import * as prettierEsTreePlugin from "prettier/plugins/estree";

import * as prettierTsPlugin from "prettier/plugins/typescript";

import { format } from "prettier/standalone";

import FileUpload from "react-mui-fileuploader";

var NestiaEditorComposer;

(function(NestiaEditorComposer) {
    NestiaEditorComposer.nest = props => compose({
        openFile: "README.md,test/start.ts",
        startScript: [ "build:test,test", "" ],
        migrate: app => app.nest(props)
    })(props);
    NestiaEditorComposer.sdk = async props => {
        console.log("NestiaEditorComposer.sdk()", props);
        return compose({
            openFile: "README.md,test/start.ts",
            startScript: [ "swagger", "hello" ],
            migrate: app => app.sdk(props)
        })(props);
    };
    const compose = config => async props => {
        if (props.files !== undefined) return {
            success: true,
            data: {
                files: props.files,
                openFile: config.openFile,
                startScript: config.startScript
            }
        };
        const result = await NestiaMigrateApplication.validate(props.document);
        if (result.success === false) return result;
        const app = result.data;
        const files = config.migrate(app);
        for (const [key, value] of Object.entries(files)) if (key.substring(key.length - 3) === ".ts") try {
            files[key] = await format(value, {
                parser: "typescript",
                plugins: [ prettierEsTreePlugin, prettierTsPlugin, jsDoc ]
            });
        } catch (exp) {
            console.log(exp);
        }
        return {
            success: true,
            data: {
                files,
                openFile: config.openFile,
                startScript: config.startScript
            }
        };
    };
})(NestiaEditorComposer || (NestiaEditorComposer = {}));

function NestiaEditorIframe(props) {
    const [id] = React.useState(`reactia-editor-div-${Math.random().toString().substring(2)}`);
    const [step, setStep] = React.useState(0);
    const [fetchError, setFetchError] = React.useState(null);
    const [operations, setOperationCount] = React.useState({});
    const [composerError, setComposerError] = React.useState(null);
    React.useEffect(() => {
        (async () => {
            setStep(0);
            const document = typeof props.swagger === "string" ? await getDocument(props.swagger) : props.swagger;
            if (typeof document === "string") {
                setFetchError(document);
                return;
            } else setOperationCount(aggregateOperation(document));
            setStep(1);
            const result = await (async () => {
                try {
                    return await NestiaEditorComposer[props.mode ?? "sdk"]({
                        document,
                        keyword: props.keyword ?? true,
                        simulate: props.simulate ?? true,
                        e2e: props.e2e ?? true,
                        package: props.package ?? "@ORGANIZATION/PROJECT"
                    });
                } catch (exp) {
                    return {
                        success: false,
                        errors: exp,
                        data: undefined
                    };
                }
            })();
            if (result.success === false) {
                setComposerError(result.errors);
                return;
            }
            setStep(2);
            StackBlitzSDK.embedProject(id, {
                title: document.info?.title ?? "Nestia Editor",
                template: "node",
                files: result.data.files
            }, {
                width: "100%",
                height: "100%",
                openFile: result.data.openFile,
                startScript: result.data.startScript
            });
        })().catch(exp => {
            console.error("unknown error", exp);
        });
    }, []);
    return jsx("div", {
        id,
        style: {
            width: "100%",
            height: "100%",
            overflow: "hidden"
        },
        children: jsxs("div", {
            style: {
                padding: 25,
                overflow: "auto"
            },
            children: [ jsx(Typography, {
                variant: "h4",
                children: "Nestia Editor"
            }), jsx("hr", {}), jsx("br", {}), jsxs(Stepper, {
                activeStep: step,
                orientation: "vertical",
                nonLinear: true,
                children: [ jsxs(Step, {
                    children: [ jsx(StepLabel, {
                        children: jsx(Typography, {
                            variant: "h5",
                            children: "Loading OpenAPI Document"
                        })
                    }), jsxs(StepContent, {
                        children: [ jsx("br", {}), jsx(CircularProgress, {
                            size: 100,
                            color: "success"
                        }), jsx("br", {}), jsx("br", {}), typeof props.swagger === "string" ? jsxs(Fragment, {
                            children: [ jsx("p", {
                                children: "Fetching OpenAPI Document from"
                            }), jsx("p", {
                                children: jsx("a", {
                                    href: props.swagger,
                                    target: "_blank",
                                    children: props.swagger
                                })
                            }) ]
                        }) : "Delivering OpenAPI Document to the composer", fetchError !== null ? jsxs(Alert, {
                            severity: "error",
                            children: [ jsx(AlertTitle, {
                                children: "Fetch Error"
                            }), fetchError ]
                        }) : null ]
                    }) ]
                }, 0), jsxs(Step, {
                    children: [ jsx(StepLabel, {
                        children: jsx(Typography, {
                            variant: "h5",
                            children: "Generating Software Development Kit"
                        })
                    }), jsxs(StepContent, {
                        children: [ jsx("br", {}), jsx(CircularProgress, {
                            size: 100,
                            color: "success"
                        }), jsx("br", {}), jsx("br", {}), "Generating SDK functions...", jsx("br", {}), jsxs("ul", {
                            children: [ jsxs("li", {
                                children: [ "total operations: #", Object.values(operations).reduce((a, b) => a + b, 0).toLocaleString() ]
                            }), Object.entries(operations).map(([method, count]) => jsxs("li", {
                                children: [ method, ": #", count.toLocaleString() ]
                            })) ]
                        }), composerError !== null ? jsxs(Fragment, {
                            children: [ jsx("br", {}), jsxs(Alert, {
                                severity: "error",
                                children: [ jsx(AlertTitle, {
                                    children: "Composition Error"
                                }), jsx("pre", {
                                    children: JSON.stringify(composerError, null, 2)
                                }) ]
                            }) ]
                        }) : null ]
                    }) ]
                }, 1), jsxs(Step, {
                    children: [ jsx(StepLabel, {
                        children: jsx(Typography, {
                            variant: "h5",
                            children: "Composing TypeScript Project"
                        })
                    }), jsx(StepContent, {}) ]
                }, 2) ]
            }) ]
        })
    });
}

const getDocument = async url => {
    try {
        const response = await fetch(url);
        if (response.status !== 200) return await response.text(); else if (url.endsWith(".yaml")) {
            const text = await response.text();
            return load(text);
        }
        return await response.json();
    } catch (error) {
        if (error instanceof Error) return error.message;
        return "Unknown error";
    }
};

const aggregateOperation = document => {
    const map = {};
    if (!(typeof document === "object" && document !== null)) return map;
    for (const collection of Object.values(document.paths ?? {})) if (typeof collection === "object" && collection !== null) for (const [method] of Object.entries(collection)) if (method === "head" || method === "get" || method === "post" || method === "patch" || method === "put" || method === "delete") map[method] = (map[method] ?? 0) + 1;
    return map;
};

function NestiaEditorFileUploader(props) {
    const [elements, setElements] = React.useState([]);
    const onChange = async array => {
        if (array.length === 0) {
            props.onChange(null, null);
            return;
        }
        const file = array[array.length - 1];
        const buffer = await file.arrayBuffer();
        const content = (new TextDecoder).decode(buffer);
        const extension = file.name.split(".").pop();
        try {
            const json = extension === "json" ? JSON.parse(content) : load(content);
            props.onChange(json, null);
        } catch {
            props.onChange(null, extension === "json" ? "Invalid JSON file" : "Invalid YAML file");
            return;
        }
        if (array.length > 1) setElements([ file ]);
    };
    return jsx(FileUpload, {
        defaultFiles: elements,
        onFilesChange: onChange,
        acceptedType: ".json, .yaml",
        getBase64: false,
        multiFile: false,
        maxUploadFiles: 1,
        title: "Swagger file uploader",
        header: "Drag and drop a Swagger file here",
        buttonLabel: "Click Here",
        rightLabel: "to select swagger.json/yaml file",
        buttonRemoveLabel: "Clear"
    });
}

function NestiaEditorUploader(props) {
    const [mode, setMode] = React.useState("sdk");
    const [keyword, setKeyword] = React.useState(true);
    const [simulate, setSimulate] = React.useState(true);
    const [e2e, setE2e] = React.useState(true);
    const [name, setName] = React.useState("@ORGINIZATION/PROJECT");
    const [document, setDocument] = React.useState(null);
    const [progress, setProgress] = React.useState(false);
    const handleError = error => {
        if (props.onError) props.onError(error); else alert(error);
    };
    const handleSwagger = (document, error) => {
        setDocument(document);
        if (error !== null) handleError(error);
    };
    const generate = async () => {
        if (document === null) return;
        setProgress(true);
        try {
            const result = await NestiaEditorComposer[mode]({
                document,
                keyword,
                e2e,
                simulate,
                package: name
            });
            if (result.success === true) {
                StackBlitzSDK.openProject({
                    title: document.info?.title ?? "Nestia Editor",
                    template: "node",
                    files: result.data.files
                }, {
                    newWindow: true,
                    openFile: result.data.openFile,
                    startScript: result.data.startScript
                });
            } else {
                handleError(JSON.stringify(result.errors, null, 2));
            }
        } catch (exp) {
            handleError(exp instanceof Error ? exp.message : "unknown error");
        }
        setProgress(false);
    };
    return jsxs(Fragment, {
        children: [ jsx(NestiaEditorFileUploader, {
            onChange: handleSwagger
        }), jsx("br", {}), jsxs(FormControl, {
            fullWidth: true,
            style: {
                paddingLeft: 15
            },
            children: [ jsx(TextField, {
                onChange: e => setName(e.target.value),
                defaultValue: name,
                label: "Package Name",
                variant: "outlined"
            }), jsx(FormLabel, {
                style: {
                    paddingTop: 20
                },
                children: " Mode "
            }), jsxs(RadioGroup, {
                defaultValue: mode,
                onChange: (_e, value) => setMode(value),
                style: {
                    paddingLeft: 15
                },
                children: [ jsx(FormControlLabel, {
                    value: "sdk",
                    control: jsx(Radio, {}),
                    label: "Software Development Kit"
                }), jsx(FormControlLabel, {
                    value: "nest",
                    control: jsx(Radio, {}),
                    label: "NestJS Project"
                }) ]
            }), jsx(FormLabel, {
                style: {
                    paddingTop: 20
                },
                children: " Options "
            }), jsx(FormControlLabel, {
                label: "Keyword Parameter",
                style: {
                    paddingTop: 5,
                    paddingLeft: 15
                },
                control: jsx(Switch, {
                    checked: keyword,
                    onChange: () => setKeyword(!keyword)
                })
            }), jsx(FormControlLabel, {
                label: "Mockup Simulator",
                style: {
                    paddingTop: 5,
                    paddingLeft: 15
                },
                control: jsx(Switch, {
                    checked: simulate,
                    onChange: () => setSimulate(!simulate)
                })
            }), jsx(FormControlLabel, {
                label: "E2E Test Functions",
                style: {
                    paddingLeft: 15
                },
                control: jsx(Switch, {
                    checked: e2e,
                    onChange: () => setE2e(!e2e)
                })
            }) ]
        }), jsx("br", {}), jsx("br", {}), jsx(Button, {
            component: "a",
            fullWidth: true,
            variant: "contained",
            color: "info",
            size: "large",
            disabled: progress === true || document === null,
            onClick: () => generate(),
            children: progress ? "Generating..." : "Generate Editor"
        }) ]
    });
}

export { NestiaEditorIframe, NestiaEditorUploader };
//# sourceMappingURL=index.mjs.map
