import React from 'react';
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
import { hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
import { DEFAULT_EMBED_CARD_WIDTH } from '@atlaskit/editor-shared-styles';
import AlignImageCenterIcon from '@atlaskit/icon/core/align-image-center';
import AlignImageLeftIcon from '@atlaskit/icon/core/align-image-left';
import AlignImageRightIcon from '@atlaskit/icon/core/align-image-right';
import AlignTextCenterIcon from '@atlaskit/icon/core/align-text-center';
import AlignTextLeftIcon from '@atlaskit/icon/core/align-text-left';
import AlignTextRightIcon from '@atlaskit/icon/core/align-text-right';
import ContentWidthWide from '@atlaskit/icon/core/content-width-wide';
import ContentWrapLeftIcon from '@atlaskit/icon/core/content-wrap-left';
import ContentWrapRightIcon from '@atlaskit/icon/core/content-wrap-right';
import FullWidthIcon from '@atlaskit/icon/core/expand-horizontal';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '../../analytics';
import { insideTable } from '../../core-utils';
import { alignCenter, alignLeft, alignRight, tooltip } from '../../keymaps';
import commonMessages, { mediaAndEmbedToolbarMessages as toolbarMessages } from '../../messages';
import { Shortcut } from '../../ui';
import { alignAttributes, isInLayoutColumn, nonWrappedLayouts } from '../../utils';

// Workaround as we don't want to import this package into `editor-common`
// We'll get type errors if this gets out of sync with `editor-plugin-width`.

export const alignmentIcons = [{
  id: 'editor.media.alignLeft',
  value: 'align-start',
  icon: () => /*#__PURE__*/React.createElement(AlignImageLeftIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: "media-toolbar-align-left-icon"
  })
}, {
  id: 'editor.media.alignCenter',
  value: 'center',
  icon: () => /*#__PURE__*/React.createElement(AlignImageCenterIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: "media-toolbar-align-center-icon"
  })
}, {
  id: 'editor.media.alignRight',
  value: 'align-end',
  icon: () => /*#__PURE__*/React.createElement(AlignImageRightIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: "media-toolbar-align-right-icon"
  })
}];
const alignmentIconsControls = [{
  id: 'editor.media.alignLeft',
  value: 'align-start',
  icon: () => /*#__PURE__*/React.createElement(AlignTextLeftIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: ""
  }),
  keyboardShortcut: alignLeft
}, {
  id: 'editor.media.alignCenter',
  value: 'center',
  icon: () => /*#__PURE__*/React.createElement(AlignTextCenterIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: ""
  }),
  keyboardShortcut: alignCenter
}, {
  id: 'editor.media.alignRight',
  value: 'align-end',
  icon: () => /*#__PURE__*/React.createElement(AlignTextRightIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: ""
  }),
  keyboardShortcut: alignRight
}];

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export const wrappingIcons = [{
  id: 'editor.media.wrapLeft',
  value: 'wrap-left',
  icon: () => /*#__PURE__*/React.createElement(ContentWrapLeftIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: "media-toolbar-wrap-left-icon"
  })
}, {
  id: 'editor.media.wrapRight',
  value: 'wrap-right',
  icon: () => /*#__PURE__*/React.createElement(ContentWrapRightIcon, {
    color: "currentColor",
    spacing: "spacious",
    label: "media-toolbar-wrap-right-icon"
  })
}];
const breakoutIcons = [{
  value: 'wide',
  icon: ContentWidthWide
}, {
  value: 'full-width',
  icon: FullWidthIcon
}];

// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @atlaskit/volt-strict-mode/no-multiple-exports
export const layoutToMessages = {
  'wrap-left': toolbarMessages.wrapLeft,
  center: commonMessages.alignImageCenter,
  'wrap-right': toolbarMessages.wrapRight,
  wide: commonMessages.layoutWide,
  'full-width': commonMessages.layoutFullWidth,
  'align-end': commonMessages.alignImageRight,
  'align-start': commonMessages.alignImageLeft
};
const getNodeWidth = (node, schema) => {
  const {
    embedCard
  } = schema.nodes;
  if (node.type === embedCard) {
    return node.attrs.originalWidth || DEFAULT_EMBED_CARD_WIDTH;
  }
  return node.firstChild && node.firstChild.attrs.width || node.attrs.width;
};
const makeAlign = (layout, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) => {
  return (state, dispatch) => {
    const {
      node
    } = state.selection;
    const {
      layout: previousLayoutType
    } = node.attrs;
    const {
      mediaSingle
    } = state.schema.nodes;
    if (!dispatch) {
      return false;
    }
    const widthPluginState = widthPluginDependencyApi === null || widthPluginDependencyApi === void 0 ? void 0 : widthPluginDependencyApi.sharedState.currentState();
    if (!node || node.type !== nodeType || !widthPluginState) {
      return false;
    }
    const nodeWidth = getNodeWidth(node, state.schema);
    const newAttrs = allowPixelResizing ?
    // with extended experience, change alignment does not change media single width
    {
      ...node.attrs,
      layout
    } : alignAttributes(layout, node.attrs, undefined, nodeWidth, widthPluginState.lineLength);
    const tr = state.tr.setNodeMarkup(state.selection.from, undefined, newAttrs);
    tr.setMeta('scrollIntoView', false);
    // when image captions are enabled, the wrong node gets selected after
    // setNodeMarkup is called
    tr.setSelection(NodeSelection.create(tr.doc, state.selection.from));
    const {
      doc: {
        type: {
          schema: {
            nodes: {
              paragraph
            }
          }
        }
      }
    } = tr;

    // see https://product-fabric.atlassian.net/browse/ED-15518 insert a new paragraph when an embedded card is wrapped left or right
    if (layout.startsWith('wrap') && paragraph && !tr.doc.nodeAt(state.selection.to) && (insideTable(state) || isInLayoutColumn(state))) {
      const emptyParaghraph = paragraph.createAndFill();
      if (emptyParaghraph) {
        tr.insert(state.selection.to, emptyParaghraph);
      }
    }
    analyticsApi === null || analyticsApi === void 0 ? void 0 : analyticsApi.attachAnalyticsEvent({
      eventType: EVENT_TYPE.TRACK,
      action: ACTION.SELECTED,
      actionSubject: ACTION_SUBJECT[node.type === mediaSingle ? 'MEDIA_SINGLE' : 'EMBEDS'],
      actionSubjectId: ACTION_SUBJECT_ID.RICH_MEDIA_LAYOUT,
      attributes: {
        previousLayoutType,
        currentLayoutType: layout
      }
    })(tr);
    dispatch(tr);
    return true;
  };
};
const getToolbarLayout = (layout, allowPixelResizing) => {
  if (nonWrappedLayouts.includes(layout) && allowPixelResizing) {
    return 'center';
  }
  return layout;
};
const mapIconsToToolbarItem = (icons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) => icons.map(toolbarItem => {
  const {
    id,
    value
  } = toolbarItem;
  return {
    id: id,
    type: 'button',
    icon: toolbarItem.icon,
    title: intl.formatMessage(layoutToMessages[value]),
    selected: getToolbarLayout(layout, allowPixelResizing) === value,
    onClick: makeAlign(value, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing),
    ...(isChangingLayoutDisabled && {
      disabled: value !== 'center'
    })
  };
});
const mapIconsToDropdownOptions = ({
  icons,
  layout,
  intl,
  nodeType,
  widthPluginDependencyApi,
  analyticsApi,
  isChangingLayoutDisabled,
  allowPixelResizing
}) => icons.map(layoutOption => {
  const {
    id,
    value
  } = layoutOption;
  return {
    id: id,
    icon: /*#__PURE__*/React.createElement(layoutOption.icon, {
      label: ""
    }),
    title: intl.formatMessage(layoutToMessages[value]),
    selected: getToolbarLayout(layout, allowPixelResizing) === value,
    onClick: makeAlign(value, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing),
    ...(layoutOption.keyboardShortcut && {
      elemAfter: /*#__PURE__*/React.createElement(Shortcut, null, tooltip(layoutOption.keyboardShortcut))
    }),
    ...(isChangingLayoutDisabled && {
      disabled: value !== 'center'
    })
  };
});
const shouldHideLayoutToolbar = (selection, {
  nodes
}, allowResizingInTables) => {
  return hasParentNodeOfType([nodes.bodiedExtension, nodes.extensionFrame, nodes.listItem, ...(expValEquals('editor_enable_image_alignment_in_expand', 'isEnabled', true) ? [] : [nodes.expand, nodes.nestedExpand]), ...(allowResizingInTables ? [] : [nodes.table])].filter(Boolean))(selection);
};
const buildLayoutButtons = (state, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowResizing, allowResizingInTables, allowWrapping = true, allowAlignment = true, isChangingLayoutDisabled, allowPixelResizing) => {
  const {
    selection
  } = state;
  if (!(selection instanceof NodeSelection) || !selection.node || !nodeType || shouldHideLayoutToolbar(selection, state.schema, allowResizingInTables)) {
    return [];
  }
  const {
    layout
  } = selection.node.attrs;
  const alignmentToolbarItems = allowAlignment ? mapIconsToToolbarItem(alignmentIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) : [];
  const wrappingToolbarItems = allowWrapping ? mapIconsToToolbarItem(wrappingIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, isChangingLayoutDisabled, allowPixelResizing) : [];
  const breakOutToolbarItems = !allowResizing ? mapIconsToToolbarItem(breakoutIcons, layout, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowPixelResizing) : [];
  const items = [...alignmentToolbarItems, ...getSeparatorBetweenAlignmentAndWrapping(allowAlignment, allowWrapping), ...wrappingToolbarItems, ...getSeparatorBeforeBreakoutItems(allowAlignment, allowWrapping, allowResizing), ...breakOutToolbarItems];
  return items;
};

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export const buildLayoutDropdown = (state, intl, nodeType, widthPluginDependencyApi, analyticsApi, allowResizing, allowResizingInTables, allowWrapping = true, allowAlignment = true, isChangingLayoutDisabled, allowPixelResizing) => {
  const {
    selection
  } = state;
  if (!(selection instanceof NodeSelection) || !selection.node || !nodeType || shouldHideLayoutToolbar(selection, state.schema, allowResizingInTables)) {
    return [];
  }
  const {
    layout
  } = selection.node.attrs;
  const icons = [];
  if (allowAlignment) {
    icons.push(...alignmentIconsControls);
  }
  if (allowWrapping) {
    icons.push(...wrappingIcons);
  }
  if (!allowResizing) {
    icons.push(...breakoutIcons);
  }
  if (icons.length === 0) {
    return [];
  }
  const selectedLayout = getSelectedLayoutIcon(icons, selection.node) || icons[0];
  if (!selectedLayout) {
    return [];
  }
  const alignmentDropdownOptions = mapIconsToDropdownOptions({
    icons,
    layout,
    intl,
    nodeType,
    widthPluginDependencyApi,
    analyticsApi,
    isChangingLayoutDisabled,
    allowPixelResizing
  });
  return [{
    type: 'dropdown',
    title: intl.formatMessage(layoutToMessages[selectedLayout.value]),
    icon: selectedLayout.icon,
    options: alignmentDropdownOptions,
    shouldFitContainer: false,
    testId: `${nodeType.name}-layout-dropdown-trigger-button`
  }];
};
const getSelectedLayoutIcon = (layoutIcons, selectedNode) => {
  const selectedLayout = selectedNode.attrs.layout;
  return layoutIcons.find(icon => icon.value === (nonWrappedLayouts.includes(selectedLayout) ? 'center' : selectedLayout));
};
const getSeparatorBetweenAlignmentAndWrapping = (allowAlignment, allowWrapping) => allowAlignment && allowWrapping ? [{
  type: 'separator'
}] : [];
const getSeparatorBeforeBreakoutItems = (allowAlignment, allowWrapping, allowResizing) => !allowResizing && (allowAlignment || allowWrapping) ? [{
  type: 'separator'
}] : [];

// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
export default buildLayoutButtons;