import SubAreaTitle from '@/components/SubAreaTitle';
import {
  AutoMLEnsembleClass,
  AutoMLResamplingStrategy,
  AutoMLTaskType,
  autoMLEnsembleClassOptions,
  autoMLResamplingStrategyOptions,
  autoMLTaskTypeOptions,
} from '@/enums';
import { Col, Form, InputNumber, Radio, Row, Select, Switch } from 'antd';

// 分类算法
const classificationAlgorithms = [
  'adaboost',
  'bernoulli_nb',
  'decision_tree',
  'extra_trees',
  'gaussian_nb',
  'gradient_boosting',
  'k_nearest_neighbors',
  'lda',
  'liblinear_svc',
  'libsvm_svc',
  'mlp',
  'multinomial_nb',
  'passive_aggressive',
  'qda',
  'random_forest',
  'sgd',
  'LightGBMClassification',
  'XGBoostClassification',
  'StackingClassification',
].map((name) => ({ label: name, value: name }));

// 回归算法
const regressorAlgorithms = [
  'adaboost',
  'ard_regression',
  'decision_tree',
  'extra_trees',
  'gaussian_process',
  'gradient_boosting',
  'k_nearest_neighbors',
  'liblinear_svr',
  'libsvm_svr',
  'mlp',
  'random_forest',
  'sgd',
  'LightGBMRegression',
  'XGBoostRegression',
].map((name) => ({ label: name, value: name }));

// 特征预处理算法
const featureAlgorithms = [
  'densifier',
  'extra_trees_preproc_for_classification',
  'extra_trees_preproc_for_regression',
  'fast_ica',
  'feature_agglomeration',
  'kernel_pca',
  'kitchen_sinks',
  'liblinear_svc_preprocessor',
  'no_preprocessing',
  'nystroem_sampler',
  'pca',
  'polynomial',
  'random_trees_embedding',
  'select_percentile_classification',
  'select_percentile_regression',
  'select_rates_classification',
  'select_rates_regression',
  'truncatedSVD',
].map((name) => ({ label: name, value: name }));

// 分类指标
export const classificationMetrics = [
  'accuracy',
  'balanced_accuracy',
  'roc_auc',
  'average_precision',
  'log_loss',
  'precision_macro',
  'precision_micro',
  'precision_samples',
  'precision_weighted',
  'recall_macro',
  'recall_micro',
  'recall_samples',
  'recall_weighted',
  'f1_macro',
  'f1_micro',
  'f1_samples',
  'f1_weighted',
].map((name) => ({ label: name, value: name }));

// 回归指标
export const regressionMetrics = [
  'mean_absolute_error',
  'mean_squared_error',
  'root_mean_squared_error',
  'mean_squared_log_error',
  'median_absolute_error',
  'r2',
].map((name) => ({ label: name, value: name }));

function ExecuteConfig() {
  const form = Form.useFormInstance();
  const task_type = Form.useWatch('task_type', form);
  const include_classifier = Form.useWatch('include_classifier', form);
  const exclude_classifier = Form.useWatch('exclude_classifier', form);
  const include_regressor = Form.useWatch('include_regressor', form);
  const exclude_regressor = Form.useWatch('exclude_regressor', form);
  const include_feature_preprocessor = Form.useWatch('include_feature_preprocessor', form);
  const exclude_feature_preprocessor = Form.useWatch('exclude_feature_preprocessor', form);

  return (
    <>
      <SubAreaTitle
        title="执行配置"
        image={require('@/assets/img/model-deployment.png')}
        style={{ marginTop: '20px', marginBottom: '24px' }}
      ></SubAreaTitle>
      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="任务类型"
            name="task_type"
            rules={[{ required: true, message: '请选择任务类型' }]}
          >
            <Radio.Group
              options={autoMLTaskTypeOptions}
              onChange={() => form.resetFields(['metrics'])}
            ></Radio.Group>
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="特征预处理算法"
            name="include_feature_preprocessor"
            tooltip="如果不选，则使用所有可能的特征预处理算法。否则，将只使用包含的特征预处理算法"
          >
            <Select
              allowClear
              placeholder="请选择特征预处理算法"
              options={featureAlgorithms}
              disabled={exclude_feature_preprocessor?.length > 0}
              mode="multiple"
              showSearch
            />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="排除特征预处理算法"
            name="exclude_feature_preprocessor"
            tooltip="如果不选，则使用所有可能的特征预处理算法。否则，将排除包含的特征预处理算法"
          >
            <Select
              allowClear
              placeholder="排除特征预处理算法"
              options={featureAlgorithms}
              disabled={include_feature_preprocessor?.length > 0}
              mode="multiple"
              showSearch
            />
          </Form.Item>
        </Col>
      </Row>

      <Form.Item dependencies={['task_type']} noStyle>
        {({ getFieldValue }) => {
          return getFieldValue('task_type') === AutoMLTaskType.Classification ? (
            <>
              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="分类算法"
                    name="include_classifier"
                    tooltip="如果不选，则使用所有可能的分类算法。否则，将只使用包含的算法"
                  >
                    <Select
                      allowClear
                      placeholder="请选择分类算法"
                      options={classificationAlgorithms}
                      mode="multiple"
                      disabled={exclude_classifier?.length > 0}
                      showSearch
                    />
                  </Form.Item>
                </Col>
              </Row>

              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="排除分类算法"
                    name="exclude_classifier"
                    tooltip="如果不选，则使用所有可能的分类算法。否则，将排除包含的算法"
                  >
                    <Select
                      allowClear
                      placeholder="排除分类算法"
                      options={classificationAlgorithms}
                      mode="multiple"
                      disabled={include_classifier?.length > 0}
                      showSearch
                    />
                  </Form.Item>
                </Col>
              </Row>
            </>
          ) : (
            <>
              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="回归算法"
                    name="include_regressor"
                    tooltip="如果不选，则使用所有可能的回归算法。否则，将只使用包含的算法"
                  >
                    <Select
                      allowClear
                      placeholder="请选择回归算法"
                      options={regressorAlgorithms}
                      mode="multiple"
                      disabled={exclude_regressor?.length > 0}
                      showSearch
                    />
                  </Form.Item>
                </Col>
              </Row>

              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="排除的回归算法"
                    name="exclude_regressor"
                    tooltip="如果不选，则使用所有可能的回归算法。否则，将排除包含的算法"
                  >
                    <Select
                      allowClear
                      placeholder="排除回归算法"
                      options={regressorAlgorithms}
                      mode="multiple"
                      disabled={include_regressor?.length > 0}
                      showSearch
                    />
                  </Form.Item>
                </Col>
              </Row>
            </>
          );
        }}
      </Form.Item>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="集成方式"
            name="ensemble_class"
            tooltip="仅使用单个最佳模型还是集成模型"
          >
            <Radio.Group options={autoMLEnsembleClassOptions}></Radio.Group>
          </Form.Item>
        </Col>
      </Row>

      <Form.Item dependencies={['ensemble_class']} noStyle>
        {({ getFieldValue }) => {
          return getFieldValue('ensemble_class') === AutoMLEnsembleClass.Default ? (
            <>
              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="集成模型数量"
                    name="ensemble_size"
                    tooltip="集成模型数量，如果设置为0，则没有集成。默认50"
                  >
                    <InputNumber placeholder="请输入集成模型数量" min={0} precision={0} />
                  </Form.Item>
                </Col>
              </Row>

              <Row gutter={8}>
                <Col span={10}>
                  <Form.Item
                    label="集成最佳模型数量"
                    name="ensemble_nbest"
                    tooltip="仅集成最佳的N个模型，必须是大于等于1的整数"
                  >
                    <InputNumber placeholder="请输入集成最佳模型数量" min={1} precision={0} />
                  </Form.Item>
                </Col>
              </Row>
            </>
          ) : null;
        }}
      </Form.Item>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="最大数量"
            name="max_models_on_disc"
            tooltip="定义在磁盘中保存的模型的最大数量。额外的模型数量将被永久删除，它设置了一个集成可以使用多少个模型的上限。必须是大于等于1的整数，默认50"
          >
            <InputNumber placeholder="请输入最大数量" min={1} precision={0} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="内存限制（MB）"
            name="memory_limit"
            tooltip="机器学习算法的内存限制（MB）。如果自动机器学习试图分配超过memory_limit MB，它将停止拟合机器学习算法。默认3072"
          >
            <InputNumber placeholder="请输入内存限制" min={0} precision={0} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="单次时间限制（秒）"
            name="per_run_time_limit"
            tooltip="单次调用机器学习模型的时间限制（以秒为单位）。如果机器学习算法运行超过时间限制，将终止模型拟合，默认600"
          >
            <InputNumber placeholder="请输入时间限制" min={0} precision={0} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="搜索时间限制（秒）"
            name="time_left_for_this_task"
            tooltip="搜索合适模型的时间限制（以秒为单位）。通过增加这个值，自动机器学习有更高的机会找到更好的模型。默认3600。"
          >
            <InputNumber placeholder="请输入搜索时间限制" min={0} precision={0} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="测试集比率"
            name="test_size"
            tooltip="将数据划分为训练数据和测试数据，测试数据集所占比例，0到1之间"
          >
            <InputNumber placeholder="请输入测试集比率" min={0} max={1} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item label="计算指标" name="scoring_functions" tooltip="需要计算并打印的指标">
            <Select
              allowClear
              placeholder="请选择计算指标"
              options={
                task_type === AutoMLTaskType.Classification
                  ? classificationMetrics
                  : regressionMetrics
              }
              showSearch
            />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item label="随机种子" name="seed" tooltip="随机种子，将决定输出文件名">
            <InputNumber placeholder="请输入随机种子" min={0} precision={0} />
          </Form.Item>
        </Col>
      </Row>

      <SubAreaTitle
        title="重采样策略"
        image={require('@/assets/img/resample-icon.png')}
        style={{ marginTop: '20px', marginBottom: '24px' }}
      ></SubAreaTitle>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="重采样策略"
            name="resampling_strategy"
            tooltip="重采样策略，分为holdout和crossValid。holdout指定训练数据划分为训练集和验证集的比例。crossValid为交叉验证。"
          >
            <Select
              allowClear
              placeholder="请选择重采样策略"
              options={autoMLResamplingStrategyOptions}
              showSearch
            />
          </Form.Item>
        </Col>
      </Row>

      <Form.Item dependencies={['resampling_strategy']} noStyle>
        {({ getFieldValue }) => {
          return getFieldValue('resampling_strategy') === AutoMLResamplingStrategy.CrossValid ? (
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="交叉验证折数"
                  name="folds"
                  tooltip="交叉验证折数必须是大于等于2的整数"
                  rules={[
                    {
                      required: true,
                      message: '请输入交叉验证折数',
                    },
                  ]}
                >
                  <InputNumber placeholder="请输入交叉验证折数" min={2} precision={0} />
                </Form.Item>
              </Col>
            </Row>
          ) : null;
        }}
      </Form.Item>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="是否打乱"
            name="shuffle"
            tooltip="拆分数据前是否打乱顺序"
            valuePropName="checked"
          >
            <Switch />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={8}>
        <Col span={10}>
          <Form.Item
            label="训练集比率"
            name="train_size"
            tooltip="重采样划分训练集和验证集，训练集的比率，0到1之间"
          >
            <InputNumber placeholder="请输入训练集比率" min={0} max={1} />
          </Form.Item>
        </Col>
      </Row>
    </>
  );
}

export default ExecuteConfig;
