/* SPDX-FileCopyrightText: 2024 Greenbone AG
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */


import React from 'react';

import styled from 'styled-components';

import {isDefined} from 'gmp/utils/identity';
import {selectSaveId} from 'gmp/utils/id';

import {NO_VALUE, YES_VALUE} from 'gmp/parser';

import {
  AUTO_DELETE_KEEP_DEFAULT_VALUE,
  HOSTS_ORDERING_SEQUENTIAL,
  AUTO_DELETE_NO,
  DEFAULT_MAX_CHECKS,
  DEFAULT_MAX_HOSTS,
} from 'gmp/models/audit';

import {
  OPENVAS_SCANNER_TYPE,
  OPENVAS_DEFAULT_SCANNER_ID,
} from 'gmp/models/scanner';

import PropTypes from 'web/utils/proptypes';
import {renderSelectItems, UNSET_VALUE} from 'web/utils/render';

import SaveDialog from 'web/components/dialog/savedialog';

import MultiSelect from 'web/components/form/multiselect';
import Select from 'web/components/form/select';
import Spinner from 'web/components/form/spinner';
import FormGroup from 'web/components/form/formgroup';
import Checkbox from 'web/components/form/checkbox';
import YesNoRadio from 'web/components/form/yesnoradio';
import TextField from 'web/components/form/textfield';

import NewIcon from 'web/components/icon/newicon';

import AddResultsToAssetsGroup from 'web/pages/tasks/addresultstoassetsgroup';
import AutoDeleteReportsGroup from 'web/pages/tasks/autodeletereportsgroup';

import useTranslation from 'web/hooks/useTranslation';
import useCapabilities from 'web/hooks/useCapabilities';

const Title = styled.div`
  flex-grow: 1;
`;

const getScanner = (scanners, scanner_id) => {
  if (!isDefined(scanners)) {
    return undefined;
  }

  return scanners.find(sc => {
    return sc.id === scanner_id;
  });
};

const ScannerSelect = ({
  changeAudit,
  isLoading,
  scannerId,
  scanners,
  onChange,
}) => {
  const [_] = useTranslation();
  return (
    <FormGroup title={_('Scanner')}>
      <Select
        name="scanner_id"
        value={scannerId}
        disabled={!changeAudit}
        items={renderSelectItems(scanners)}
        isLoading={isLoading}
        onChange={onChange}
      />
    </FormGroup>
  );
};

ScannerSelect.propTypes = {
  changeAudit: PropTypes.bool.isRequired,
  isLoading: PropTypes.bool,
  policies: PropTypes.shape({
    [OPENVAS_SCANNER_TYPE]: PropTypes.array,
  }),
  scannerId: PropTypes.id.isRequired,
  scanners: PropTypes.array.isRequired,
  onChange: PropTypes.func.isRequired,
};

const AuditDialog = ({
  alertIds = [],
  alerts = [],
  alterable = NO_VALUE,
  auto_delete = AUTO_DELETE_NO,
  auto_delete_data = AUTO_DELETE_KEEP_DEFAULT_VALUE,
  comment = '',
  fromPolicy = false,
  hostsOrdering = HOSTS_ORDERING_SEQUENTIAL,
  in_assets = YES_VALUE,
  isLoadingScanners = false,
  maxChecks = DEFAULT_MAX_CHECKS,
  maxHosts = DEFAULT_MAX_HOSTS,
  name,
  policies = [],
  policyId,
  scannerId = OPENVAS_DEFAULT_SCANNER_ID,
  scanners = [
    {
      id: OPENVAS_DEFAULT_SCANNER_ID,
      scannerType: OPENVAS_SCANNER_TYPE,
    },
  ],
  scheduleId = UNSET_VALUE,
  schedulePeriods = NO_VALUE,
  schedules = [],
  targetId,
  targets,
  audit,
  title,
  onClose,
  onNewAlertClick,
  onNewScheduleClick,
  onNewTargetClick,
  onSave,
  onScannerChange,
  onChange,
  ...data
}) => {
  const [_] = useTranslation();
  const capabilities = useCapabilities();

  title = title || _('New Audit');
  name = name || _('Unnamed');

  const targetItems = renderSelectItems(targets);

  const scheduleItems = renderSelectItems(schedules, UNSET_VALUE);

  const policyItems = renderSelectItems(policies);

  policyId = selectSaveId(policies, policyId, undefined);

  const alertItems = renderSelectItems(alerts);

  // having an audit means we are editing an audit
  const hasAudit = isDefined(audit);

  const changeAudit = hasAudit ? audit.isChangeable() : true;

  const scanner = getScanner(scanners, scannerId);
  const scannerType = isDefined(scanner) ? scanner.scannerType : undefined;

  const uncontrolledData = {
    ...data,
    alterable,
    auto_delete,
    auto_delete_data,
    comment,
    hostsOrdering,
    in_assets,
    maxChecks,
    maxHosts,
    name,
    scannerId,
    scannerType,
    audit,
  };

  const controlledData = {
    alertIds,
    policyId,
    scannerId,
    scannerType,
    scheduleId,
    targetId,
  };

  return (
    <SaveDialog
      title={title}
      onClose={onClose}
      onSave={onSave}
      defaultValues={uncontrolledData}
      values={controlledData}
    >
      {({values: state, onValueChange}) => {
        return (
          <>
            <FormGroup title={_('Name')}>
              <TextField
                name="name"
                value={state.name}
                onChange={onValueChange}
              />
            </FormGroup>

            <FormGroup title={_('Comment')}>
              <TextField
                name="comment"
                value={state.comment}
                onChange={onValueChange}
              />
            </FormGroup>

            <FormGroup title={_('Scan Targets')} direction="row">
              <Select
                name="targetId"
                disabled={!changeAudit}
                items={targetItems}
                value={state.targetId}
                onChange={onChange}
              />
              {changeAudit && (
                <NewIcon
                  title={_('Create a new target')}
                  onClick={onNewTargetClick}
                />
              )}
            </FormGroup>

            {capabilities.mayOp('get_alerts') && (
              <FormGroup title={_('Alerts')} direction="row">
                <MultiSelect
                  name="alertIds"
                  items={alertItems}
                  value={state.alertIds}
                  onChange={onChange}
                />
                <NewIcon
                  title={_('Create a new alert')}
                  onClick={onNewAlertClick}
                />
              </FormGroup>
            )}

            {capabilities.mayOp('get_schedules') && (
              <FormGroup title={_('Schedule')} direction="row">
                <Select
                  name="scheduleId"
                  value={state.scheduleId}
                  items={scheduleItems}
                  onChange={onChange}
                />
                <Checkbox
                  name="schedulePeriods"
                  checked={state.schedulePeriods === YES_VALUE}
                  checkedValue={YES_VALUE}
                  unCheckedValue={NO_VALUE}
                  title={_('Once')}
                  onChange={onValueChange}
                />
                <NewIcon
                  title={_('Create a new schedule')}
                  onClick={onNewScheduleClick}
                />
              </FormGroup>
            )}

            <AddResultsToAssetsGroup
              inAssets={state.in_assets}
              onChange={onValueChange}
            />

            {changeAudit && (
              <FormGroup title={_('Alterable Audit')}>
                <YesNoRadio
                  name="alterable"
                  disabled={audit && !audit.isNew()}
                  value={state.alterable}
                  onChange={onValueChange}
                />
              </FormGroup>
            )}

            <AutoDeleteReportsGroup
              autoDelete={state.auto_delete}
              autoDeleteData={state.auto_delete_data}
              onChange={onValueChange}
            />

            <Title
              title={
                changeAudit
                  ? null
                  : _(
                      'This setting is not alterable once the audit has been run at least once.',
                    )
              }
            >
              <ScannerSelect
                scanners={scanners}
                scannerId={state.scannerId}
                changeAudit={changeAudit}
                isLoading={isLoadingScanners}
                onChange={onScannerChange}
              />
            </Title>

            <FormGroup title={_('Policy')}>
              <Select
                name="policyId"
                disabled={!changeAudit || hasAudit || fromPolicy}
                items={policyItems}
                value={policyId}
                onChange={onChange}
              />
            </FormGroup>

            <FormGroup titleSize="4" title={_('Order for target hosts')}>
              <Select
                name="hostsOrdering"
                items={[
                  {
                    value: 'sequential',
                    label: _('Sequential'),
                  },
                  {
                    value: 'random',
                    label: _('Random'),
                  },
                  {
                    value: 'reverse',
                    label: _('Reverse'),
                  },
                ]}
                value={state.hostsOrdering}
                onChange={onValueChange}
              />
            </FormGroup>
            <FormGroup title={_('Maximum concurrently executed NVTs per host')}>
              <Spinner
                name="maxChecks"
                type="int"
                min="0"
                value={state.maxChecks}
                onChange={onValueChange}
              />
            </FormGroup>
            <FormGroup title={_('Maximum concurrently scanned hosts')}>
              <Spinner
                name="maxHosts"
                type="int"
                min="0"
                value={state.maxHosts}
                onChange={onValueChange}
              />
            </FormGroup>
          </>
        );
      }}
    </SaveDialog>
  );
};

AuditDialog.propTypes = {
  alertIds: PropTypes.array,
  alerts: PropTypes.array,
  alterable: PropTypes.yesno,
  audit: PropTypes.model,
  auto_delete: PropTypes.oneOf(['keep', 'no']),
  auto_delete_data: PropTypes.number,
  comment: PropTypes.string,
  fromPolicy: PropTypes.bool,
  hostsOrdering: PropTypes.oneOf(['sequential', 'random', 'reverse']),
  in_assets: PropTypes.yesno,
  isLoadingScanners: PropTypes.bool,
  maxChecks: PropTypes.number,
  maxHosts: PropTypes.number,
  name: PropTypes.string,
  policies: PropTypes.arrayOf(PropTypes.model),
  policyId: PropTypes.idOrZero,
  scannerId: PropTypes.idOrZero,
  scanners: PropTypes.array,
  scheduleId: PropTypes.idOrZero,
  schedulePeriods: PropTypes.yesno,
  schedules: PropTypes.array,
  targetId: PropTypes.idOrZero,
  targets: PropTypes.array,
  title: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  onClose: PropTypes.func.isRequired,
  onNewAlertClick: PropTypes.func.isRequired,
  onNewScheduleClick: PropTypes.func.isRequired,
  onNewTargetClick: PropTypes.func.isRequired,
  onSave: PropTypes.func.isRequired,
  onScannerChange: PropTypes.func.isRequired,
};

export default AuditDialog;

// vim: set ts=2 sw=2 tw=80:
