"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HostsTableModals = exports.useHostsTable = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_redux_1 = require("react-redux");
const common_1 = require("../../../common");
const AdditionalNTPSourcesDialog_1 = require("../../../common/components/hosts/AdditionalNTPSourcesDialog");
const api_1 = require("../../../common/api");
const slice_1 = require("../../store/slices/current-cluster/slice");
const ModalDialogsContext_1 = require("./ModalDialogsContext");
const utils_1 = require("./utils");
const hosts_1 = require("../../../common/components/hosts");
const HostsTable_1 = tslib_1.__importDefault(require("../../../common/components/hosts/HostsTable"));
const ResetHostModal_1 = tslib_1.__importDefault(require("./ResetHostModal"));
const DeleteHostModal_1 = tslib_1.__importDefault(require("./DeleteHostModal"));
const fetchEvents_1 = require("../fetching/fetchEvents");
const services_1 = require("../../services");
const UpdateDay2ApiVipModal_1 = tslib_1.__importDefault(require("./UpdateDay2ApiVipModal"));
const usePagination_1 = require("../../../common/components/hosts/usePagination");
const use_translation_wrapper_1 = require("../../../common/hooks/use-translation-wrapper");
const HardwareStatus_1 = require("./HardwareStatus");
const ClusterWizardContext_1 = require("../clusterWizard/ClusterWizardContext");
const selectors_1 = require("../../store/slices/current-cluster/selectors");
const use_feature_1 = require("../../hooks/use-feature");
const useHostsTable = (cluster) => {
    const isSingleClusterFeatureEnabled = (0, use_feature_1.useFeature)('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
    const { addAlert } = (0, common_1.useAlerts)();
    const { eventsDialog, editHostDialog, deleteHostDialog, resetHostDialog, massUpdateHostnameDialog, massDeleteHostDialog, } = (0, ModalDialogsContext_1.useModalDialogsContext)();
    const { resetCluster } = React.useContext(common_1.AddHostsContext);
    const { isViewerMode } = (0, react_redux_1.useSelector)(selectors_1.selectCurrentClusterPermissionsState);
    const { t } = (0, use_translation_wrapper_1.useTranslation)();
    const dispatch = (0, react_redux_1.useDispatch)();
    const hostActions = React.useMemo(() => ({
        onDeleteHost: (host) => {
            const inventory = (0, common_1.getInventory)(host);
            deleteHostDialog.open({
                hostId: host.id,
                hostname: ((host === null || host === void 0 ? void 0 : host.requestedHostname) || (inventory === null || inventory === void 0 ? void 0 : inventory.hostname)),
            });
        },
        onInstallHost: (host) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
            const hostId = host.id;
            try {
                const { data } = yield services_1.HostsService.install(host);
                resetCluster ? void resetCluster() : dispatch((0, slice_1.updateHost)(data));
            }
            catch (e) {
                (0, api_1.handleApiError)(e, () => addAlert({ title: `Failed to enable host ${hostId}`, message: (0, api_1.getApiErrorMessage)(e) }));
            }
        }),
    }), [dispatch, resetCluster, addAlert, deleteHostDialog]);
    const onViewHostEvents = React.useCallback((host) => {
        const { id, requestedHostname } = host;
        const inventory = (0, common_1.getInventory)(host);
        const hostname = requestedHostname || (inventory === null || inventory === void 0 ? void 0 : inventory.hostname) || id;
        eventsDialog.open({ hostId: id, hostname });
    }, [eventsDialog]);
    const onEditHost = React.useCallback((host) => {
        const inventory = (0, common_1.getInventory)(host);
        editHostDialog.open({ host, inventory });
    }, [editHostDialog]);
    const onHostReset = React.useCallback((host) => {
        const inventory = (0, common_1.getInventory)(host);
        const hostname = (host === null || host === void 0 ? void 0 : host.requestedHostname) || (inventory === null || inventory === void 0 ? void 0 : inventory.hostname) || '';
        resetHostDialog.open({ hostId: host.id, hostname });
    }, [resetHostDialog]);
    const onDownloadHostLogs = React.useCallback((host) => {
        void (0, utils_1.downloadHostInstallationLogs)(addAlert, host);
    }, [addAlert]);
    const onDiskRole = React.useCallback((hostId, diskId, role) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        try {
            if (!diskId) {
                // noinspection ExceptionCaughtLocallyJS
                throw new Error(`Cannot update disk role in host ${hostId}\nMissing diskId`);
            }
            const host = services_1.ClustersService.findHost(cluster.hosts, hostId);
            if (!host) {
                throw new Error(`No host found with id:${hostId}`);
            }
            const { data } = yield services_1.HostsService.updateDiskRole(host, diskId, role);
            resetCluster ? void resetCluster() : dispatch((0, slice_1.updateHost)(data));
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => addAlert({ title: 'Failed to set disk role', message: (0, api_1.getApiErrorMessage)(e) }));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    }), [dispatch, resetCluster, addAlert, cluster.hosts]);
    const onExcludedODF = React.useCallback((hostId, nodeLabels) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        try {
            const host = services_1.ClustersService.findHost(cluster.hosts, hostId);
            if (!host) {
                throw new Error(`No host found with id:${hostId}`);
            }
            const { data } = yield services_1.HostsService.updateHostODF(host, nodeLabels);
            resetCluster ? yield resetCluster() : dispatch((0, slice_1.updateHost)(data));
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => addAlert({ title: 'Failed to update ODF status', message: (0, api_1.getApiErrorMessage)(e) }));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    }), [cluster.hosts, resetCluster, dispatch, addAlert]);
    const onUpdateDay2ApiVip = React.useCallback((apiVip, onError) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        try {
            const { data } = yield services_1.ClustersService.update(cluster.id, cluster.tags, {
                apiVipDnsName: apiVip,
            });
            dispatch((0, slice_1.updateCluster)(data));
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => onError((0, api_1.getApiErrorMessage)(e)));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    }), [cluster.id, cluster.tags, dispatch]);
    const onAdditionalNtpSource = React.useMemo(() => (...args) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { return yield (0, utils_1.onAdditionalNtpSourceAction)(dispatch, cluster, ...args); }), [cluster, dispatch]);
    const updateDiskSkipFormatting = React.useCallback((shouldFormatDisk, hostId, diskId) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        try {
            if (!cluster.id) {
                throw new Error(`Failed to update disks skip formatting state in host ${hostId}\nMissing cluster id`);
            }
            if (!diskId) {
                throw new Error(`Failed to update disks skip formatting state in host ${hostId}\nMissing disk id`);
            }
            const host = services_1.ClustersService.findHost(cluster.hosts, hostId);
            if (!host) {
                throw new Error(`No host found with id:${hostId}`);
            }
            const { data } = yield services_1.HostsService.updateFormattingDisks(host, diskId, !shouldFormatDisk);
            resetCluster ? void resetCluster() : dispatch((0, slice_1.updateHost)(data));
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => addAlert({
                title: 'Failed to set disks skip formatting',
                message: (0, api_1.getApiErrorMessage)(e),
            }));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    }), [dispatch, addAlert, cluster, resetCluster]);
    const actionChecks = React.useMemo(() => ({
        canEditRole: (host) => {
            if (isSingleClusterFeatureEnabled && host.bootstrap) {
                return false;
            }
            return !isViewerMode && (0, hosts_1.canEditRole)(cluster.status, host.status, (0, common_1.isSNO)(cluster));
        },
        canInstallHost: (host) => !isViewerMode && (0, hosts_1.canInstallHost)(cluster, host.status),
        canEditDisks: (host) => !isViewerMode && (0, hosts_1.canEditDisks)(cluster.status, host.status),
        canEnable: (host) => !isViewerMode && (0, hosts_1.canEnable)(cluster.status, host.status),
        canDisable: (host) => !isViewerMode && (0, hosts_1.canDisable)(cluster.status, host.status),
        canDelete: (host) => !isViewerMode && (0, hosts_1.canDelete)(cluster.status, host.status),
        canEditHost: (host) => !isViewerMode && (0, hosts_1.canEditHost)(cluster.status, host.status),
        canReset: (host) => !isViewerMode && (0, hosts_1.canReset)(cluster.status, host.status),
        canEditHostname: (host) => !isViewerMode && (0, hosts_1.canEditHostname)(cluster.status, host),
    }), [cluster, isViewerMode, isSingleClusterFeatureEnabled]);
    const onReset = React.useCallback(() => {
        var _a;
        const reset = (hostId) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
            if (hostId) {
                try {
                    const host = services_1.ClustersService.findHost(cluster.hosts, hostId);
                    if (!host) {
                        throw new Error(`No host found with id:${hostId}`);
                    }
                    const { data } = yield services_1.HostsService.reset(host);
                    resetCluster ? void resetCluster() : dispatch((0, slice_1.updateHost)(data));
                }
                catch (e) {
                    (0, api_1.handleApiError)(e, () => addAlert({
                        title: `Failed to reset host ${hostId}`,
                        message: (0, api_1.getApiErrorMessage)(e),
                    }));
                }
            }
        });
        void reset((_a = resetHostDialog.data) === null || _a === void 0 ? void 0 : _a.hostId);
        resetHostDialog.close();
    }, [addAlert, cluster.hosts, dispatch, resetCluster, resetHostDialog]);
    const onDelete = React.useCallback(() => {
        var _a;
        const deleteHost = (hostId) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
            if (hostId) {
                try {
                    const host = services_1.ClustersService.findHost(cluster.hosts, hostId);
                    if (!host) {
                        throw new Error(`No host found with id:${hostId}`);
                    }
                    yield services_1.HostsService.delete(host);
                    resetCluster ? void resetCluster() : dispatch((0, slice_1.forceReload)());
                }
                catch (e) {
                    (0, api_1.handleApiError)(e, () => addAlert({
                        title: `Failed to delete host ${hostId}`,
                        message: (0, api_1.getApiErrorMessage)(e),
                    }));
                }
            }
        });
        void deleteHost((_a = deleteHostDialog.data) === null || _a === void 0 ? void 0 : _a.hostId);
        deleteHostDialog.close();
    }, [deleteHostDialog, cluster.hosts, resetCluster, dispatch, addAlert]);
    const onEditRole = React.useCallback((host, role) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        try {
            if (!host.clusterId) {
                // noinspection ExceptionCaughtLocallyJS
                throw new Error(`Failed to edit role in host: ${host.id}.\nMissing cluster_id`);
            }
            const { data } = yield services_1.HostsService.updateRole(host, role);
            if (resetCluster) {
                void resetCluster();
            }
            else {
                dispatch((0, slice_1.updateHost)(data));
                // Reload to obtain cluster-level validations that may be affected by role change
                dispatch((0, slice_1.forceReload)());
            }
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => addAlert({ title: 'Failed to set role', message: (0, api_1.getApiErrorMessage)(e) }));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    }), [addAlert, dispatch, resetCluster]);
    const actionResolver = React.useMemo(() => (0, common_1.hostActionResolver)(Object.assign(Object.assign(Object.assign({ t }, actionChecks), { onEditRole,
        onDiskRole,
        onExcludedODF,
        onEditHost,
        onHostReset,
        onDownloadHostLogs,
        onViewHostEvents,
        canDownloadHostLogs: hosts_1.canDownloadHostLogs }), hostActions)), [
        t,
        actionChecks,
        hostActions,
        onEditRole,
        onDiskRole,
        onEditHost,
        onHostReset,
        onDownloadHostLogs,
        onExcludedODF,
        onViewHostEvents,
    ]);
    const [selectedHostIDs, setSelectedHostIDs] = React.useState([]);
    const onSelect = React.useCallback((obj, isSelected) => {
        if (isSelected) {
            setSelectedHostIDs([...selectedHostIDs, obj.id]);
        }
        else {
            setSelectedHostIDs(selectedHostIDs.filter((sh) => sh !== obj.id));
        }
    }, [selectedHostIDs]);
    const onMassChangeHostname = React.useCallback(() => {
        var _a;
        if (selectedHostIDs.length === 1) {
            const host = (_a = cluster.hosts) === null || _a === void 0 ? void 0 : _a.find((host) => host.id === selectedHostIDs[0]);
            return host && onEditHost(host);
        }
        return massUpdateHostnameDialog.open({
            hostIDs: selectedHostIDs,
            cluster,
            reloadCluster: () => (resetCluster ? void resetCluster() : dispatch((0, slice_1.forceReload)())),
        });
    }, [selectedHostIDs, massUpdateHostnameDialog, cluster, onEditHost, resetCluster, dispatch]);
    const onMassDeleteHost = React.useCallback(() => {
        var _a;
        if (selectedHostIDs.length === 1) {
            const host = (_a = cluster.hosts) === null || _a === void 0 ? void 0 : _a.find((host) => host.id === selectedHostIDs[0]);
            return (host &&
                deleteHostDialog.open({
                    hostId: host.id,
                    hostname: host === null || host === void 0 ? void 0 : host.requestedHostname,
                }));
        }
        else {
            return massDeleteHostDialog.open({
                hosts: (cluster.hosts || []).filter((h) => selectedHostIDs.includes(h.id)),
                onDelete: (host) => services_1.HostsService.delete(host),
                reloadCluster: () => (resetCluster ? void resetCluster() : dispatch((0, slice_1.forceReload)())),
            });
        }
    }, [
        selectedHostIDs,
        cluster.hosts,
        deleteHostDialog,
        massDeleteHostDialog,
        resetCluster,
        dispatch,
    ]);
    return {
        onDiskRole,
        onEditHost,
        actionChecks,
        onEditRole,
        actionResolver,
        onReset,
        onDelete,
        onAdditionalNtpSource,
        onUpdateDay2ApiVip,
        onSelect: isViewerMode ? undefined : onSelect,
        selectedHostIDs,
        setSelectedHostIDs,
        onMassChangeHostname,
        onMassDeleteHost,
        updateDiskSkipFormatting,
    };
};
exports.useHostsTable = useHostsTable;
const HostsTableModals = ({ cluster, onDelete, onReset, onAdditionalNtpSource, onUpdateDay2ApiVip, }) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
    const { wizardPerPage, setWizardPerPage } = React.useContext(ClusterWizardContext_1.ClusterWizardContext) || {};
    const dispatch = (0, react_redux_1.useDispatch)();
    const { resetCluster } = React.useContext(common_1.AddHostsContext);
    const { uiState } = (0, react_redux_1.useSelector)(selectors_1.selectCurrentClusterState);
    const { t } = (0, use_translation_wrapper_1.useTranslation)();
    const { eventsDialog, editHostDialog, deleteHostDialog, resetHostDialog, additionalNTPSourcesDialog, UpdateDay2ApiVipDialog, massUpdateHostnameDialog, massDeleteHostDialog, } = (0, ModalDialogsContext_1.useModalDialogsContext)();
    const content = React.useMemo(() => [(0, common_1.hostnameColumn)(t), (0, HardwareStatus_1.hardwareStatusColumn)({ isWithinModal: true })], [t]);
    const paginationProps = (0, usePagination_1.usePagination)(((_b = (_a = massDeleteHostDialog.data) === null || _a === void 0 ? void 0 : _a.hosts) === null || _b === void 0 ? void 0 : _b.length) || 0, wizardPerPage, setWizardPerPage);
    if (uiState === common_1.ResourceUIState.UPDATE_ERROR) {
        // Do not show a modal beneath the ServerUpdateError
        return null;
    }
    return (React.createElement(React.Fragment, null,
        eventsDialog.isOpen && (React.createElement(common_1.EventsModal, { isOpen: true, title: `Host Events${eventsDialog.isOpen ? `: ${(_c = eventsDialog.data) === null || _c === void 0 ? void 0 : _c.hostname}` : ''}`, entityKind: "host", cluster: cluster, hostId: (_d = eventsDialog.data) === null || _d === void 0 ? void 0 : _d.hostId, onClose: eventsDialog.close, onFetchEvents: fetchEvents_1.onFetchEvents })),
        resetHostDialog.isOpen && (React.createElement(ResetHostModal_1.default, { isOpen: true, hostname: (_e = resetHostDialog.data) === null || _e === void 0 ? void 0 : _e.hostname, onClose: resetHostDialog.close, onReset: onReset })),
        deleteHostDialog.isOpen && (React.createElement(DeleteHostModal_1.default, { isOpen: true, hostname: (_f = deleteHostDialog.data) === null || _f === void 0 ? void 0 : _f.hostname, onClose: deleteHostDialog.close, onDelete: onDelete })),
        editHostDialog.isOpen && (React.createElement(hosts_1.EditHostModal, { isOpen: true, host: (_g = editHostDialog.data) === null || _g === void 0 ? void 0 : _g.host, inventory: (_h = editHostDialog.data) === null || _h === void 0 ? void 0 : _h.inventory, usedHostnames: (_j = cluster === null || cluster === void 0 ? void 0 : cluster.hosts) === null || _j === void 0 ? void 0 : _j.map((h) => h.requestedHostname).filter((h) => h), onClose: editHostDialog.close, onSave: (values) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
                const host = services_1.ClustersService.findHost(cluster.hosts, values.hostId);
                if (!host) {
                    throw new Error(`No host found with id:${values.hostId}`);
                }
                const { data } = yield services_1.HostsService.updateHostName(host, values.hostname);
                resetCluster ? void resetCluster() : dispatch((0, slice_1.updateHost)(data));
                editHostDialog.close();
            }), onHostSaveError: (e) => {
                if ((0, api_1.isUnknownServerError)(e)) {
                    dispatch((0, slice_1.setServerUpdateError)());
                    editHostDialog.close();
                }
            }, getEditErrorMessage: (e) => {
                (0, api_1.handleApiError)(e);
                return (0, api_1.getApiErrorMessage)(e);
            } })),
        additionalNTPSourcesDialog.isOpen && (React.createElement(AdditionalNTPSourcesDialog_1.AdditionalNTPSourcesDialog, { isOpen: true, additionalNtpSource: cluster.additionalNtpSource, onClose: additionalNTPSourcesDialog.close, onAdditionalNtpSource: onAdditionalNtpSource })),
        UpdateDay2ApiVipDialog.isOpen && (React.createElement(UpdateDay2ApiVipModal_1.default, { isOpen: true, onClose: UpdateDay2ApiVipDialog.close, onUpdateDay2ApiVip: onUpdateDay2ApiVip, currentApiVip: cluster.apiVipDnsName })),
        massUpdateHostnameDialog.isOpen && (React.createElement(common_1.MassChangeHostnameModal, { isOpen: true, onClose: massUpdateHostnameDialog.close, hosts: ((_l = (_k = massUpdateHostnameDialog.data) === null || _k === void 0 ? void 0 : _k.cluster) === null || _l === void 0 ? void 0 : _l.hosts) || [], selectedHostIDs: ((_m = massUpdateHostnameDialog.data) === null || _m === void 0 ? void 0 : _m.hostIDs) || [], onChangeHostname: (host, hostname) => services_1.HostsService.updateHostName(host, hostname), onHostSaveError: (e) => {
                if ((0, api_1.isUnknownServerError)(e)) {
                    dispatch((0, slice_1.setServerUpdateError)());
                    editHostDialog.close();
                }
            }, canChangeHostname: () => [true, undefined], reloadCluster: (_o = massUpdateHostnameDialog.data) === null || _o === void 0 ? void 0 : _o.reloadCluster })),
        massDeleteHostDialog.isOpen && (React.createElement(common_1.MassDeleteHostModal, { isOpen: true, onClose: massDeleteHostDialog.close, hosts: ((_p = massDeleteHostDialog.data) === null || _p === void 0 ? void 0 : _p.hosts) || [], onDelete: (_q = massDeleteHostDialog.data) === null || _q === void 0 ? void 0 : _q.onDelete, reloadCluster: (_r = massDeleteHostDialog.data) === null || _r === void 0 ? void 0 : _r.reloadCluster },
            React.createElement(HostsTable_1.default, Object.assign({ hosts: ((_s = massDeleteHostDialog.data) === null || _s === void 0 ? void 0 : _s.hosts) || [], content: content }, paginationProps),
                React.createElement("div", null, "No hosts selected"))))));
};
exports.HostsTableModals = HostsTableModals;
//# sourceMappingURL=use-hosts-table.js.map