//
// Copyright 2020 DXOS.org
//
import React, { useCallback, useMemo } from 'react';
import { Obj } from '@dxos/echo';
import { Format } from '@dxos/echo/internal';
import { log } from '@dxos/log';
import { useClient } from '@dxos/react-client';
import { useSpaces } from '@dxos/react-client/echo';
import { useFileDownload } from '@dxos/react-ui';
import { DynamicTable } from '@dxos/react-ui-table';
import { createFilename } from '@dxos/util';
import { PanelContainer } from '../../../components';
import { useDevtoolsDispatch } from '../../../hooks';
import { exportData, importData } from './backup';
import { DialogRestoreSpace } from './DialogRestoreSpace';
const rowActions = [
    { id: 'toggleOpen', label: 'Toggle space open closed' },
    { id: 'snapshot', label: 'Download space snapshot' },
    { id: 'archive', label: 'Download space archive' },
];
export const SpaceListPanel = ({ onSelect }) => {
    const client = useClient();
    const spaces = useSpaces({ all: true });
    const setState = useDevtoolsDispatch();
    const download = useFileDownload();
    const rows = useMemo(() => {
        return spaces.map((space) => {
            const { open, ready } = space.internal.data.metrics ?? {};
            return {
                id: space.id.toString(),
                name: space.isOpen ? space.properties.name : undefined,
                objects: -1, // TODO(dmaretskyi): Fix this.
                members: space.members.get().length,
                startup: open && ready ? ready.getTime() - open.getTime() : -1,
                isDefault: client.spaces.default === space,
                isOpen: space.isOpen,
            };
        });
    }, [spaces]);
    const handleRowClicked = useCallback((row) => {
        if (!row) {
            return;
        }
        const selectedId = row.id;
        const space = spaces.find((space) => space.key.toString() === selectedId);
        setState((state) => ({ ...state, space }));
        onSelect?.(row._original);
    }, [onSelect, setState, spaces]);
    const handleToggleOpen = useCallback(async (spaceId) => {
        const space = spaces.find((space) => space.id === spaceId);
        if (space.isOpen) {
            await space.close();
        }
        else {
            await space.open();
        }
    }, [spaces]);
    const handleSnapshot = useCallback(async (spaceId) => {
        const space = spaces.find((space) => space.id === spaceId);
        await space.waitUntilReady();
        const backupBlob = await exportData(space);
        download(backupBlob, createFilename({ parts: [space.id], ext: 'json' }));
    }, [download, spaces]);
    const handleArchive = useCallback(async (spaceId) => {
        const space = spaces.find((space) => space.id === spaceId);
        const archive = await space.internal.export();
        download(new Blob([archive.contents]), archive.filename);
    }, [download, spaces]);
    const handleImport = useCallback(async (backup) => {
        try {
            if (backup instanceof File) {
                if (backup.type === 'application/json') {
                    // Validate backup.
                    const backupString = await backup.text();
                    JSON.parse(backupString);
                    // Import space.
                    const space = await client.spaces.create();
                    await space.waitUntilReady();
                    await importData(space, backup);
                    Obj.change(space.properties, (p) => {
                        p.name = p.name + ' - IMPORTED';
                    });
                }
                else if (backup.type === 'application/x-tar') {
                    const archive = {
                        filename: backup.name,
                        contents: new Uint8Array(await backup.arrayBuffer()),
                    };
                    await client.spaces.import(archive);
                }
                else {
                    throw new Error('Invalid backup type');
                }
            }
            else {
                // For Blob type
                const backupString = await backup.text();
                JSON.parse(backupString);
                const space = await client.spaces.create();
                await space.waitUntilReady();
                await importData(space, backup);
                Obj.change(space.properties, (p) => {
                    p.name = p.name + ' - IMPORTED';
                });
            }
        }
        catch (err) {
            log.catch(err);
        }
    }, [client]);
    const properties = useMemo(() => [
        { name: 'id', format: Format.TypeFormat.DID },
        { name: 'name', format: Format.TypeFormat.String },
        { name: 'objects', format: Format.TypeFormat.Number, size: 120 },
        { name: 'members', format: Format.TypeFormat.Number, size: 120 },
        { name: 'startup', format: Format.TypeFormat.Number, size: 120 },
        { name: 'isDefault', format: Format.TypeFormat.Boolean, title: 'default?', size: 120 },
        { name: 'isOpen', format: Format.TypeFormat.Boolean, title: 'open?', size: 120 },
    ], []);
    const handleRowAction = (actionId, item) => {
        const spaceId = item.id;
        if (actionId === 'toggleOpen') {
            void handleToggleOpen(spaceId);
        }
        else if (actionId === 'snapshot') {
            void handleSnapshot(spaceId);
        }
        else if (actionId === 'archive') {
            void handleArchive(spaceId);
        }
    };
    const features = useMemo(() => ({ selection: { enabled: true, mode: 'single' } }), []);
    return (React.createElement(PanelContainer, { classNames: 'overflow-auto flex-1' },
        React.createElement(DialogRestoreSpace, { handleFile: handleImport }),
        React.createElement(DynamicTable, { properties: properties, rows: rows, features: features, rowActions: rowActions, onRowClick: handleRowClicked, onRowAction: handleRowAction })));
};
//# sourceMappingURL=SpaceListPanel.js.map