"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importDefault(require("react"));
const react_redux_1 = require("react-redux");
const formik_1 = require("formik");
const react_core_1 = require("@patternfly/react-core");
const common_1 = require("../../../../common");
const ClusterDefaultConfigurationContext_1 = require("../ClusterDefaultConfigurationContext");
const ClusterWizardContext_1 = require("../../clusterWizard/ClusterWizardContext");
const ClusterWizardFooter_1 = tslib_1.__importDefault(require("../../clusterWizard/ClusterWizardFooter"));
const wizardTransition_1 = require("../../clusterWizard/wizardTransition");
const ClusterWizardNavigation_1 = tslib_1.__importDefault(require("../../clusterWizard/ClusterWizardNavigation"));
const NetworkConfigurationTable_1 = tslib_1.__importDefault(require("./NetworkConfigurationTable"));
const useInfraEnv_1 = tslib_1.__importDefault(require("../../../hooks/useInfraEnv"));
const selectors_1 = require("../../../store/slices/current-cluster/selectors");
const networkConfigurationValidation_1 = require("./networkConfigurationValidation");
const NetworkConfiguration_1 = tslib_1.__importDefault(require("./NetworkConfiguration"));
const sentry_1 = require("../../../sentry");
const services_1 = require("../../../services");
const slice_1 = require("../../../store/slices/current-cluster/slice");
const api_1 = require("../../../../common/api");
const hooks_1 = require("../../../hooks");
const newFeatureSupportLevels_1 = require("../../../../common/components/newFeatureSupportLevels");
const use_feature_1 = require("../../../hooks/use-feature");
const NetworkConfigurationForm = ({ cluster, hostSubnets, defaultNetworkSettings, infraEnv }) => {
    const { alerts } = (0, common_1.useAlerts)();
    const clusterWizardContext = (0, ClusterWizardContext_1.useClusterWizardContext)();
    const { isViewerMode } = (0, react_redux_1.useSelector)(selectors_1.selectCurrentClusterPermissionsState);
    const { errors, touched, isSubmitting, isValid, setFieldValue, values } = (0, formik_1.useFormikContext)();
    const isAutoSaveRunning = (0, common_1.useFormikAutoSave)();
    const errorFields = (0, common_1.getFormikErrorFields)(errors, touched);
    const isSingleClusterFeatureEnabled = (0, use_feature_1.useFeature)('ASSISTED_INSTALLER_SINGLE_CLUSTER_FEATURE');
    const { addAlert } = (0, common_1.useAlerts)();
    const dispatch = (0, react_redux_1.useDispatch)();
    // DHCP allocation is currently not supported for Nutanix hosts
    // https://issues.redhat.com/browse/MGMT-12382
    const isHostsPlatformTypeNutanix = react_1.default.useMemo(() => { var _a; return ((_a = cluster.platform) === null || _a === void 0 ? void 0 : _a.type) === 'nutanix'; }, [cluster.platform]);
    react_1.default.useEffect(() => {
        if (isHostsPlatformTypeNutanix && values.vipDhcpAllocation) {
            setFieldValue('vipDhcpAllocation', false);
        }
    }, [isHostsPlatformTypeNutanix, setFieldValue, values.vipDhcpAllocation]);
    const onNext = react_1.default.useCallback(() => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        if (isSingleClusterFeatureEnabled) {
            try {
                yield common_1.ClustersAPI.updateInstallConfig(cluster.id, JSON.stringify(JSON.stringify({
                    featureSet: 'CustomNoUpgrade',
                    featureGates: ['NoRegistryClusterInstall=true'],
                })));
            }
            catch (e) {
                (0, api_1.handleApiError)(e, () => addAlert({
                    title: 'Failed to update install-config',
                    message: (0, api_1.getApiErrorMessage)(e),
                }));
                if ((0, api_1.isUnknownServerError)(e)) {
                    dispatch((0, slice_1.setServerUpdateError)());
                }
                return;
            }
        }
        clusterWizardContext.moveNext();
    }), [addAlert, cluster.id, clusterWizardContext, dispatch, isSingleClusterFeatureEnabled]);
    const isNextDisabled = isSubmitting ||
        isAutoSaveRunning ||
        !!alerts.length ||
        !isValid ||
        !(0, wizardTransition_1.canNextNetwork)({ cluster });
    const footer = (react_1.default.createElement(ClusterWizardFooter_1.default, { cluster: cluster, errorFields: errorFields, isSubmitting: isSubmitting, isNextDisabled: isNextDisabled, isWaitingForHosts: !(0, wizardTransition_1.canNextNetwork)({ cluster }), onNext: () => void onNext(), onBack: () => clusterWizardContext.moveBack(), isBackDisabled: isSubmitting || isAutoSaveRunning }));
    return (react_1.default.createElement(common_1.ClusterWizardStep, { navigation: react_1.default.createElement(ClusterWizardNavigation_1.default, { cluster: cluster }), footer: footer },
        react_1.default.createElement(react_core_1.Form, null,
            react_1.default.createElement(react_core_1.Grid, { hasGutter: true },
                react_1.default.createElement(react_core_1.GridItem, null,
                    react_1.default.createElement(common_1.ClusterWizardStepHeader, null, "Networking")),
                react_1.default.createElement(react_core_1.GridItem, { span: 12, lg: 10, xl: 9, xl2: 7 },
                    react_1.default.createElement(react_core_1.Grid, { hasGutter: true },
                        react_1.default.createElement(NetworkConfiguration_1.default, { cluster: cluster, hostSubnets: hostSubnets, defaultNetworkSettings: defaultNetworkSettings, isVipDhcpAllocationDisabled: isHostsPlatformTypeNutanix }),
                        react_1.default.createElement(common_1.SecurityFields, { clusterSshKey: cluster.sshPublicKey, imageSshKey: infraEnv === null || infraEnv === void 0 ? void 0 : infraEnv.sshAuthorizedKey, isDisabled: isViewerMode }))),
                react_1.default.createElement(react_core_1.GridItem, null,
                    react_1.default.createElement(react_core_1.Content, { component: "h2" }, "Host inventory"),
                    react_1.default.createElement(NetworkConfigurationTable_1.default, { cluster: cluster }))))));
};
const NetworkConfigurationPage = ({ cluster }) => {
    const { t } = (0, common_1.useTranslation)();
    const pullSecret = (0, hooks_1.usePullSecret)();
    const { infraEnv, error: infraEnvError, isLoading, } = (0, useInfraEnv_1.default)(cluster.id, cluster.cpuArchitecture
        ? cluster.cpuArchitecture
        : common_1.CpuArchitecture.USE_DAY1_ARCHITECTURE, cluster.name, pullSecret, cluster.openshiftVersion);
    const defaultNetworkValues = (0, ClusterDefaultConfigurationContext_1.useDefaultConfiguration)([
        'clusterNetworksDualstack',
        'clusterNetworksIpv4',
        'serviceNetworksDualstack',
        'serviceNetworksIpv4',
    ]);
    const { addAlert, clearAlerts, alerts } = (0, common_1.useAlerts)();
    const dispatch = (0, react_redux_1.useDispatch)();
    const { isViewerMode } = (0, react_redux_1.useSelector)(selectors_1.selectCurrentClusterPermissionsState);
    const hostSubnets = react_1.default.useMemo(() => (0, common_1.getHostSubnets)(cluster, true), [cluster]);
    const featureSupportLevelData = (0, newFeatureSupportLevels_1.useNewFeatureSupportLevel)();
    const isClusterManagedNetworkingUnsupported = !featureSupportLevelData.isFeatureSupported('CLUSTER_MANAGED_NETWORKING');
    const initialValues = react_1.default.useMemo(() => (0, networkConfigurationValidation_1.getNetworkInitialValues)(cluster, defaultNetworkValues, isClusterManagedNetworkingUnsupported), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    const memoizedValidationSchema = react_1.default.useMemo(() => (0, networkConfigurationValidation_1.getNetworkConfigurationValidationSchema)(initialValues, hostSubnets, t, cluster.openshiftVersion), [initialValues, hostSubnets, t, cluster.openshiftVersion]);
    react_1.default.useEffect(() => {
        if (infraEnvError) {
            const title = `Failed to retrieve infra env (clusterId: ${cluster.id})`;
            //TODO(brotman) add handling of existing errors to alerts context
            if (alerts.find((alert) => alert.title === title)) {
                return;
            }
            (0, sentry_1.captureException)(infraEnvError, title);
            addAlert({
                title,
                message: infraEnvError,
            });
        }
        //shouldn't respond to cluster polling. shouldn't respond to alerts changes so remove alert wouldn't trigger adding it back
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [infraEnvError]);
    const handleSubmit = (values) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
        clearAlerts();
        // update the cluster configuration
        try {
            const isMultiNodeCluster = !(0, common_1.isSNO)(cluster);
            const isUserManagedNetworking = values.managedNetworkingType === 'userManaged';
            // Only send VIPs that have a non-empty IP;
            const apiVips = (values.apiVips || []).filter((v) => { var _a; return ((_a = v === null || v === void 0 ? void 0 : v.ip) !== null && _a !== void 0 ? _a : '').trim() !== ''; });
            const ingressVips = (values.ingressVips || []).filter((v) => { var _a; return ((_a = v === null || v === void 0 ? void 0 : v.ip) !== null && _a !== void 0 ? _a : '').trim() !== ''; });
            const params = {
                apiVips,
                ingressVips,
                sshPublicKey: values.sshPublicKey,
                vipDhcpAllocation: values.vipDhcpAllocation,
                networkType: values.networkType,
                machineNetworks: values.machineNetworks,
                clusterNetworks: values.clusterNetworks,
                serviceNetworks: values.serviceNetworks,
                userManagedNetworking: isUserManagedNetworking,
            };
            if (params.userManagedNetworking) {
                params.apiVips = [];
                params.ingressVips = [];
                if (isMultiNodeCluster) {
                    delete params.machineNetworks;
                }
            }
            else {
                // cluster-managed can't be chosen in SNO, so this must be a multi-node cluster
                if (values.vipDhcpAllocation) {
                    delete params.apiVips;
                    delete params.ingressVips;
                }
                else if (values.stackType === common_1.SINGLE_STACK) {
                    // The API will rebuild the default machineNetwork
                    params.machineNetworks = [];
                }
            }
            const { data } = yield services_1.ClustersService.update(cluster.id, cluster.tags, params);
            dispatch((0, slice_1.updateClusterBase)(data));
        }
        catch (e) {
            (0, api_1.handleApiError)(e, () => addAlert({ title: 'Failed to update the cluster', message: (0, api_1.getApiErrorMessage)(e) }));
            if ((0, api_1.isUnknownServerError)(e)) {
                dispatch((0, slice_1.setServerUpdateError)());
            }
        }
    });
    if (isLoading) {
        return react_1.default.createElement(common_1.LoadingState, null);
    }
    const onSubmit = isViewerMode ? () => Promise.resolve() : handleSubmit;
    return (react_1.default.createElement(formik_1.Formik, { initialValues: initialValues, validationSchema: memoizedValidationSchema, onSubmit: onSubmit, validateOnMount: true },
        react_1.default.createElement(NetworkConfigurationForm, { cluster: cluster, hostSubnets: hostSubnets, defaultNetworkSettings: defaultNetworkValues, infraEnv: infraEnv })));
};
exports.default = NetworkConfigurationPage;
//# sourceMappingURL=NetworkConfigurationForm.js.map