import { useEffect } from 'react';

import {
  DataTransformerID,
  TransformerRegistryItem,
  TransformerUIProps,
  TransformerCategory,
  fieldMatchers,
  FieldMatcherID,
  Field,
} from '@grafana/data';
import { InlineField, Select } from '@grafana/ui';
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
import { NumberInput } from 'app/core/components/OptionsUI/NumberInput';

import { getTransformationContent } from '../docs/getTransformationContent';

import { DEFAULTS, ModelType, RegressionTransformer, RegressionTransformerOptions } from './regression';

const fieldNamePickerSettings = {
  editor: FieldNamePicker,
  id: '',
  name: '',
  settings: { width: 24, isClearable: false },
};

const LABEL_WIDTH = 20;

export const RegressionTransformerEditor = ({
  input,
  options,
  onChange,
}: TransformerUIProps<RegressionTransformerOptions>) => {
  const modelTypeOptions = [
    { label: 'Linear', value: ModelType.linear },
    { label: 'Polynomial', value: ModelType.polynomial },
  ];

  useEffect(() => {
    let x: Field | undefined;
    let y: Field | undefined;
    if (!options.xFieldName) {
      const timeMatcher = fieldMatchers.get(FieldMatcherID.firstTimeField).get({});
      for (const frame of input) {
        x = frame.fields.find((field) => timeMatcher(field, frame, input));
        if (x) {
          break;
        }
      }
      if (!x) {
        const firstMatcher = fieldMatchers.get(FieldMatcherID.numeric).get({});
        for (const frame of input) {
          x = frame.fields.find((field) => firstMatcher(field, frame, input));
          if (x) {
            break;
          }
        }
      }
    }
    if (!options.yFieldName) {
      const numberMatcher = fieldMatchers.get(FieldMatcherID.numeric).get({});
      for (const frame of input) {
        y = frame.fields.find((field) => numberMatcher(field, frame, input) && field !== x);
        if (y) {
          break;
        }
      }
    }

    if (x && y) {
      onChange({ ...options, xFieldName: x.name, yFieldName: y.name });
    }
  });

  return (
    <>
      <InlineField labelWidth={LABEL_WIDTH} label="X field">
        <FieldNamePicker
          context={{ data: input }}
          value={options.xFieldName ?? ''}
          item={fieldNamePickerSettings}
          onChange={(v) => {
            onChange({ ...options, xFieldName: v });
          }}
        ></FieldNamePicker>
      </InlineField>
      <InlineField labelWidth={LABEL_WIDTH} label="Y field">
        <FieldNamePicker
          context={{ data: input }}
          value={options.yFieldName ?? ''}
          item={fieldNamePickerSettings}
          onChange={(v) => {
            onChange({ ...options, yFieldName: v });
          }}
        ></FieldNamePicker>
      </InlineField>
      <InlineField labelWidth={LABEL_WIDTH} label="Model type">
        <Select
          value={options.modelType ?? DEFAULTS.modelType}
          onChange={(v) => {
            onChange({ ...options, modelType: v.value ?? DEFAULTS.modelType });
          }}
          options={modelTypeOptions}
        ></Select>
      </InlineField>
      <InlineField labelWidth={LABEL_WIDTH} label="Predicted points" tooltip={'Number of X,Y points to predict'}>
        <NumberInput
          value={options.predictionCount ?? DEFAULTS.predictionCount}
          onChange={(v) => {
            onChange({ ...options, predictionCount: v });
          }}
        ></NumberInput>
      </InlineField>
      {options.modelType === ModelType.polynomial && (
        <InlineField labelWidth={LABEL_WIDTH} label="Degree">
          <Select<number>
            value={options.degree ?? DEFAULTS.degree}
            options={[
              { label: 'Quadratic', value: 2 },
              { label: 'Cubic', value: 3 },
              { label: 'Quartic', value: 4 },
              { label: 'Quintic', value: 5 },
            ]}
            onChange={(v) => {
              onChange({ ...options, degree: v.value });
            }}
          ></Select>
        </InlineField>
      )}
    </>
  );
};

export const regressionTransformerRegistryItem: TransformerRegistryItem<RegressionTransformerOptions> = {
  id: DataTransformerID.regression,
  editor: RegressionTransformerEditor,
  transformation: RegressionTransformer,
  name: RegressionTransformer.name,
  description: RegressionTransformer.description,
  categories: new Set([TransformerCategory.CalculateNewFields]),
  help: getTransformationContent(DataTransformerID.regression).helperDocs,
};
