import { jsx, jsxs } from 'react/jsx-runtime';
import { css } from '@emotion/css';
import { useState } from 'react';
import { DragDropContext, Droppable } from '@hello-pangea/dnd';
import { useMountedState, usePrevious } from 'react-use';
import '@grafana/data';
import { useStyles2, Cascader, Button } from '@grafana/ui';
import { OperationEditor } from './OperationEditor.js';
import '../../QueryEditor/types.js';
import 'lodash';
import '../../QueryEditor/EditorList.js';
import { EditorStack } from '../../QueryEditor/EditorStack.js';
import '../../QueryEditor/Space.js';
import '../../QueryEditor/QueryHeader.js';
import 'react-virtualized-auto-sizer';
import 'sql-formatter-plus';
import '../../SQLEditor/standardSql/language.js';
import 'uuid';
import '@grafana/runtime';
import '../../SQLEditor/utils/debugger.js';
import '../../SQLEditor/standardSql/macros.js';
import '../../QueryEditor/visual-query-builder/AwesomeQueryBuilder.js';
import '../../QueryEditor/visual-query-builder/WhereRow.js';
import '../../QueryEditor/visual-query-builder/EditorField.js';
import 'rxjs';
import 'rxjs/operators';

function OperationList({
  query,
  datasource,
  queryModeller,
  onChange,
  onRunQuery,
  highlightedOp,
  timeRange,
  isConflictingOperation
}) {
  const styles = useStyles2(getStyles);
  const { operations } = query;
  const opsToHighlight = useOperationsHighlight(operations);
  const [cascaderOpen, setCascaderOpen] = useState(false);
  const onOperationChange = (index, update) => {
    const updatedList = [...operations];
    updatedList.splice(index, 1, update);
    onChange({ ...query, operations: updatedList });
  };
  const onRemove = (index) => {
    const updatedList = [...operations.slice(0, index), ...operations.slice(index + 1)];
    onChange({ ...query, operations: updatedList });
  };
  const onToggle = (index) => {
    onOperationChange(index, { ...operations[index], disabled: !operations[index].disabled });
  };
  const addOptions = queryModeller.getCategories().map((category) => {
    return {
      value: category,
      label: category,
      items: queryModeller.getOperationsForCategory(category).map((operation) => ({
        value: operation.id,
        label: operation.name,
        isLeaf: true
      }))
    };
  });
  const onAddOperation = (value) => {
    const operationDef = queryModeller.getOperationDefinition(value);
    if (!operationDef) {
      return;
    }
    onChange(operationDef.addOperationHandler(operationDef, query, queryModeller));
    setCascaderOpen(false);
  };
  const onDragEnd = (result) => {
    if (!result.destination) {
      return;
    }
    const updatedList = [...operations];
    const element = updatedList[result.source.index];
    updatedList.splice(result.source.index, 1);
    updatedList.splice(result.destination.index, 0, element);
    onChange({ ...query, operations: updatedList });
  };
  const onCascaderBlur = () => {
    setCascaderOpen(false);
  };
  return /* @__PURE__ */ jsx(EditorStack, { gap: 1, direction: "column", children: /* @__PURE__ */ jsxs(EditorStack, { gap: 1, children: [
    operations.length > 0 && /* @__PURE__ */ jsx(DragDropContext, { onDragEnd, children: /* @__PURE__ */ jsx(Droppable, { droppableId: "sortable-field-mappings", direction: "horizontal", children: (provided) => /* @__PURE__ */ jsxs("div", { className: styles.operationList, ref: provided.innerRef, ...provided.droppableProps, children: [
      operations.map((op, index) => {
        return /* @__PURE__ */ jsx(
          OperationEditor,
          {
            queryModeller,
            index,
            operation: op,
            query,
            datasource,
            onChange: onOperationChange,
            onRemove,
            onToggle,
            onRunQuery,
            flash: opsToHighlight[index],
            highlight: highlightedOp === op,
            timeRange,
            isConflictingOperation
          },
          op.id + JSON.stringify(op.params) + index
        );
      }),
      provided.placeholder
    ] }) }) }),
    /* @__PURE__ */ jsx("div", { className: styles.addButton, children: cascaderOpen ? /* @__PURE__ */ jsx(
      Cascader,
      {
        options: addOptions,
        onSelect: onAddOperation,
        onBlur: onCascaderBlur,
        autoFocus: true,
        alwaysOpen: true,
        hideActiveLevelLabel: true,
        placeholder: "Search"
      }
    ) : /* @__PURE__ */ jsx(Button, { icon: "plus", variant: "secondary", onClick: () => setCascaderOpen(true), title: "Add operation", children: "Operations" }) })
  ] }) });
}
function useOperationsHighlight(operations) {
  const isMounted = useMountedState();
  const prevOperations = usePrevious(operations);
  if (!isMounted()) {
    return operations.map(() => false);
  }
  if (!prevOperations) {
    return operations.map(() => true);
  }
  let newOps = [];
  if (prevOperations.length - 1 === operations.length && operations.every((op) => prevOperations.includes(op))) {
    return operations.map(() => false);
  }
  if (prevOperations.length + 1 === operations.length && prevOperations.every((op) => operations.includes(op))) {
    const newOp = operations.find((op) => !prevOperations.includes(op));
    newOps = operations.map((op) => {
      return op === newOp;
    });
  } else {
    newOps = operations.map((op, index) => {
      var _a;
      return !isSameOp(op.id, (_a = prevOperations[index]) == null ? undefined : _a.id);
    });
  }
  return newOps;
}
function isSameOp(op1, op2) {
  return op1 === op2 || `__${op1}_by` === op2 || op1 === `__${op2}_by`;
}
const getStyles = (theme) => {
  return {
    heading: css({
      label: "heading",
      fontSize: 12,
      fontWeight: theme.typography.fontWeightMedium,
      marginBottom: 0
    }),
    operationList: css({
      label: "operationList",
      display: "flex",
      flexWrap: "wrap",
      gap: theme.spacing(2)
    }),
    addButton: css({
      label: "addButton",
      width: 126,
      paddingBottom: theme.spacing(1)
    })
  };
};

export { OperationList };
//# sourceMappingURL=OperationList.js.map
