//
// Copyright 2020 DXOS.org
//
import * as Option from 'effect/Option';
import * as SchemaAST from 'effect/SchemaAST';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { DXN, Entity, Format, Type } from '@dxos/echo';
import { Toolbar } from '@dxos/react-ui';
import { DynamicTable } from '@dxos/react-ui-table';
import { mx } from '@dxos/ui-theme';
import { ObjectViewer, PanelContainer, Placeholder, Searchbar } from '../../../components';
import { DataSpaceSelector } from '../../../containers';
import { useDevtoolsState } from '../../../hooks';
const textFilter = (text) => {
    if (!text) {
        return () => true;
    }
    // TODO(burdon): Structured query (e.g., "type:Text").
    const matcher = new RegExp(text, 'i');
    return (item) => {
        let match = false;
        match ||= !!Type.getDXN(item)?.toString().match(matcher);
        match ||= !!SchemaAST.getTitleAnnotation(item.ast).pipe(Option.getOrUndefined)?.match(matcher);
        match ||= !!SchemaAST.getDescriptionAnnotation(item.ast).pipe(Option.getOrUndefined)?.match(matcher);
        return match;
    };
};
const useSchemaQuery = (space) => {
    const [schema, setSchema] = useState([]);
    useEffect(() => {
        if (!space) {
            return;
        }
        return space.db.schemaRegistry.query().subscribe((query) => {
            setSchema([...space.internal.db.graph.schemaRegistry.schemas, ...query.results]);
        }, { fire: true });
    }, [space]);
    return schema;
};
export const SchemaPanel = (props) => {
    const state = useDevtoolsState();
    const space = props.space ?? state.space;
    const schema = useSchemaQuery(space);
    const [filter, setFilter] = useState('');
    // NOTE: Always call setSelected with a function: setSelected(() => item) because schema is a class constructor.
    const [selected, setSelected] = useState();
    const onNavigate = (dxn) => {
        const selectedSchema = schema.find((item) => Type.getDXN(item) && DXN.equals(Type.getDXN(item), dxn));
        if (selectedSchema) {
            setSelected(() => selectedSchema);
            return;
        }
        const typeDXN = dxn.asTypeDXN();
        if (typeDXN && typeDXN.version === undefined) {
            const latestSchema = schema.find((item) => Type.getDXN(item)?.toString().startsWith(dxn.toString()));
            if (latestSchema) {
                setSelected(() => latestSchema);
            }
        }
    };
    const itemSelect = (item) => {
        setSelected(() => item);
    };
    const dataProperties = useMemo(() => [
        { name: 'typename', format: Format.TypeFormat.String },
        { name: 'version', format: Format.TypeFormat.String, size: 100 },
        {
            name: 'kind',
            format: Format.TypeFormat.SingleSelect,
            size: 100,
            config: {
                options: [
                    { id: 'object', title: 'OBJECT', color: 'indigo' },
                    { id: 'relation', title: 'RELATION', color: 'green' },
                ],
            },
        },
    ], []);
    const dataRows = useMemo(() => {
        return schema
            .filter(textFilter(filter))
            .map((item) => ({
            id: Type.getDXN(item),
            typename: Type.getTypename(item) ?? '',
            version: Type.getVersion(item) ?? '',
            kind: Entity.getKind(item),
            _original: item, // Store the original item for selection
        }))
            .toSorted((a, b) => (a.id?.toString() ?? '').localeCompare(b.id?.toString() ?? ''));
    }, [schema, filter]);
    const handleObjectRowClicked = useCallback((row) => {
        if (!row) {
            setSelected(undefined);
            return;
        }
        itemSelect(row._original);
    }, []);
    const features = useMemo(() => ({ selection: { enabled: true, mode: 'single' } }), []);
    return (React.createElement(PanelContainer, { toolbar: React.createElement(Toolbar.Root, null,
            !props.space && React.createElement(DataSpaceSelector, null),
            React.createElement(Searchbar, { placeholder: 'Filter...', onChange: setFilter })) },
        React.createElement("div", { className: 'bs-full grid grid-cols-[4fr_3fr] overflow-hidden' },
            React.createElement("div", { className: 'flex flex-col is-full overflow-hidden' },
                React.createElement(DynamicTable, { properties: dataProperties, rows: dataRows, features: features, onRowClick: handleObjectRowClicked }),
                React.createElement("div", { className: mx('bs-[--statusbar-size]', 'flex shrink-0 justify-end items-center gap-2', 'bg-baseSurface text-description') },
                    React.createElement("div", { className: 'text-sm pie-2' },
                        "Objects: ",
                        dataRows.length))),
            React.createElement("div", { className: 'min-bs-0 bs-full !border-separator border-is border-bs' },
                React.createElement("div", { className: mx('p-1 min-bs-0 bs-full overflow-auto') }, selected ? (React.createElement(ObjectViewer, { object: Type.toJsonSchema(selected), id: Type.getDXN(selected)?.toString(), onNavigate: onNavigate })) : (React.createElement(Placeholder, { label: 'Data' })))))));
};
//# sourceMappingURL=SchemaPanel.js.map