import { defineMessages } from 'react-intl';
import cloneDeep from 'lodash/cloneDeep';

import ViewTitleBlock from '@plone/volto/components/manage/Blocks/Title/View';
import ViewDescriptionBlock from '@plone/volto/components/manage/Blocks/Description/View';
import ViewToCBlock from '@plone/volto/components/manage/Blocks/ToC/View';
import ViewImageBlock from '@plone/volto/components/manage/Blocks/Image/View';
import ViewLeadImageBlock from '@plone/volto/components/manage/Blocks/LeadImage/View';
import ViewListingBlock from '@plone/volto/components/manage/Blocks/Listing/View';
import ViewVideoBlock from '@plone/volto/components/manage/Blocks/Video/View';
import ViewMapBlock from '@plone/volto/components/manage/Blocks/Maps/View';
import ViewHTMLBlock from '@plone/volto/components/manage/Blocks/HTML/View';

import EditTitleBlock from '@plone/volto/components/manage/Blocks/Title/Edit';
import EditDescriptionBlock from '@plone/volto/components/manage/Blocks/Description/Edit';
import EditToCBlock from '@plone/volto/components/manage/Blocks/ToC/Edit';
import EditImageBlock from '@plone/volto/components/manage/Blocks/Image/Edit';
import EditLeadImageBlock from '@plone/volto/components/manage/Blocks/LeadImage/Edit';
import EditListingBlock from '@plone/volto/components/manage/Blocks/Listing/Edit';
import DefaultNoResultsComponent from '@plone/volto/components/manage/Blocks/Listing/DefaultNoResultsComponent';
import GalleryNoResultsComponent from '@plone/volto/components/manage/Blocks/Listing/GalleryNoResultsComponent';
import DefaultListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/DefaultTemplate';
import SummaryListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/SummaryTemplate';
import EditVideoBlock from '@plone/volto/components/manage/Blocks/Video/Edit';
import EditMapBlock from '@plone/volto/components/manage/Blocks/Maps/Edit';
import EditHTMLBlock from '@plone/volto/components/manage/Blocks/HTML/Edit';

import descriptionSVG from '@plone/volto/icons/description.svg';
import titleSVG from '@plone/volto/icons/text.svg';
import cameraSVG from '@plone/volto/icons/camera.svg';
import videoSVG from '@plone/volto/icons/videocamera.svg';
import globeSVG from '@plone/volto/icons/globe.svg';
import codeSVG from '@plone/volto/icons/code.svg';
import listingBlockSVG from '@plone/volto/icons/content-listing.svg';
import tocSVG from '@plone/volto/icons/list-bullet.svg';
import searchSVG from '@plone/volto/icons/zoom.svg';
import gridSVG from '@plone/volto/icons/grid-block.svg';
import imagesSVG from '@plone/volto/icons/images.svg';

import ImageGalleryListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/ImageGallery';
import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema';
import ImageSettingsSchema from '@plone/volto/components/manage/Blocks/Image/LayoutSchema';
import ToCSettingsSchema from '@plone/volto/components/manage/Blocks/ToC/Schema';

import GridBlockView from '@plone/volto/components/manage/Blocks/Grid/View';
import GridBlockEdit from '@plone/volto/components/manage/Blocks/Grid/Edit';
import { GridBlockDataAdapter } from '@plone/volto/components/manage/Blocks/Grid/adapter';
import { GridBlockSchema } from '@plone/volto/components/manage/Blocks/Grid/schema';
import GridTemplates from '@plone/volto/components/manage/Blocks/Grid/templates';
import { gridTeaserDisableStylingSchema } from '@plone/volto/components/manage/Blocks/Teaser/schema';
import { gridImageDisableSizeAndPositionHandlersSchema } from '@plone/volto/components/manage/Blocks/Image/schema';

import SearchBlockView from '@plone/volto/components/manage/Blocks/Search/SearchBlockView';
import SearchBlockEdit from '@plone/volto/components/manage/Blocks/Search/SearchBlockEdit';

import RightColumnFacets from '@plone/volto/components/manage/Blocks/Search/layout/RightColumnFacets';
import LeftColumnFacets from '@plone/volto/components/manage/Blocks/Search/layout/LeftColumnFacets';
import TopSideFacets from '@plone/volto/components/manage/Blocks/Search/layout/TopSideFacets';
import {
  SelectFacet,
  CheckboxFacet,
  DateRangeFacet,
  ToggleFacet,
  ToggleFacetFilterListEntry,
  SelectFacetFilterListEntry,
  DateRangeFacetFilterListEntry,
} from '@plone/volto/components/manage/Blocks/Search/components';
import getListingBlockAsyncData from '@plone/volto/components/manage/Blocks/Listing/getAsyncData';
import { getImageBlockSizes } from '@plone/volto/components/manage/Blocks/Image/utils';
import { getLeadImageBlockSizes } from '@plone/volto/components/manage/Blocks/LeadImage/utils';
import { getTeaserBlockSizes } from '@plone/volto/components/manage/Blocks/Teaser/utils';

// block sidebar schemas (not the Dexterity Layout block settings schemas)
import ListingBlockSchema from '@plone/volto/components/manage/Blocks/Listing/schema';
import SearchBlockSchema from '@plone/volto/components/manage/Blocks/Search/schema';
import VideoBlockSchema from '@plone/volto/components/manage/Blocks/Video/schema';

import ToCVariations from '@plone/volto/components/manage/Blocks/ToC/variations';

import TeaserViewBlock from '@plone/volto/components/manage/Blocks/Teaser/View';
import TeaserEditBlock from '@plone/volto/components/manage/Blocks/Teaser/Edit';
import TeaserBlockDefaultBody from '@plone/volto/components/manage/Blocks/Teaser/DefaultBody';
import { TeaserSchema } from '@plone/volto/components/manage/Blocks/Teaser/schema';
import { TeaserBlockDataAdapter } from '@plone/volto/components/manage/Blocks/Teaser/adapter';

defineMessages({
  title: {
    id: 'title',
    defaultMessage: 'Title',
  },
  description: {
    id: 'description',
    defaultMessage: 'Description',
  },
  text: {
    id: 'text',
    defaultMessage: 'Text',
  },
  toc: {
    id: 'toc',
    defaultMessage: 'Table of Contents',
  },
  image: {
    id: 'image',
    defaultMessage: 'Image',
  },
  video: {
    id: 'video',
    defaultMessage: 'Video',
  },
  hero: {
    id: 'hero',
    defaultMessage: 'Hero',
  },
  table: {
    id: 'table',
    defaultMessage: 'Table',
  },
  maps: {
    id: 'maps',
    defaultMessage: 'Maps',
  },
  html: {
    id: 'html',
    defaultMessage: 'HTML',
  },
  leadimage: {
    id: 'leadimage',
    defaultMessage: 'Lead Image Field',
  },
  listing: {
    id: 'listing',
    defaultMessage: 'Listing',
  },
  // Groups
  mostUsed: {
    id: 'mostUsed',
    defaultMessage: 'Most used',
  },
  media: {
    id: 'media',
    defaultMessage: 'Media',
  },
  common: {
    id: 'common',
    defaultMessage: 'Common',
  },
  // Listing block variations
  summary: {
    id: 'Summary',
    defaultMessage: 'Summary',
  },
  imageGallery: {
    id: 'Image gallery',
    defaultMessage: 'Image gallery',
  },
  // Search block variations
  facetsRightSide: {
    id: 'Facets on right side',
    defaultMessage: 'Facets on right side',
  },
  facetsLeftSide: {
    id: 'Facets on left side',
    defaultMessage: 'Facets on left side',
  },
  facetsTopSide: {
    id: 'Facets on top',
    defaultMessage: 'Facets on top',
  },
  selectFacet: {
    id: 'selectFacet',
    defaultMessage: 'Select',
  },
  checkboxFacet: {
    id: 'checkboxFacet',
    defaultMessage: 'Checkbox',
  },
  daterangeFacet: {
    id: 'daterangeFacet',
    defaultMessage: 'Date Range',
  },
  toggleFacet: {
    id: 'toggleFacet',
    defaultMessage: 'Toggle',
  },
  // BBB Table messages
  Table: {
    id: 'Table',
    defaultMessage: 'Table',
  },
  cell: {
    id: 'Cell',
    defaultMessage: 'Cell',
  },
  insertRowBefore: {
    id: 'Insert row before',
    defaultMessage: 'Insert row before',
  },
  insertRowAfter: {
    id: 'Insert row after',
    defaultMessage: 'Insert row after',
  },
  deleteRow: {
    id: 'Delete row',
    defaultMessage: 'Delete row',
  },
  insertColBefore: {
    id: 'Insert col before',
    defaultMessage: 'Insert col before',
  },
  insertColAfter: {
    id: 'Insert col after',
    defaultMessage: 'Insert col after',
  },
  deleteCol: {
    id: 'Delete col',
    defaultMessage: 'Delete col',
  },
  fixed: {
    id: 'Fixed width table cells',
    defaultMessage: 'Fixed width columns',
  },
  compact: {
    id: 'Make the table compact',
    defaultMessage: 'Reduce cell padding',
  },
  basic: {
    id: 'Reduce complexity',
    defaultMessage: 'Minimalistic table design',
  },
  celled: {
    id: 'Divide each row into separate cells',
    defaultMessage: 'Add border to inner columns',
  },
  striped: {
    id: 'Stripe alternate rows with color',
    defaultMessage: 'Alternate row background color',
  },
  headerCell: {
    id: 'Header cell',
    defaultMessage: 'Header cell',
  },
});

const groupBlocksOrder = [
  { id: 'mostUsed', title: 'Most used' },
  { id: 'text', title: 'Text' },
  { id: 'media', title: 'Media' },
  { id: 'common', title: 'Common' },
];

const blocksConfig = {
  title: {
    id: 'title',
    title: 'Title',
    icon: titleSVG,
    group: 'text',
    view: ViewTitleBlock,
    edit: EditTitleBlock,
    schema: BlockSettingsSchema,
    restricted: ({ properties, block }) =>
      properties.blocks_layout?.items?.find(
        (uid) => properties.blocks?.[uid]?.['@type'] === block.id,
      ),
    mostUsed: false,
    blockHasOwnFocusManagement: true,
    sidebarTab: 0,
  },
  description: {
    id: 'description',
    title: 'Description',
    icon: descriptionSVG,
    group: 'text',
    view: ViewDescriptionBlock,
    edit: EditDescriptionBlock,
    schema: BlockSettingsSchema,
    restricted: false,
    mostUsed: false,
    blockHasOwnFocusManagement: true,
    sidebarTab: 0,
  },
  image: {
    id: 'image',
    title: 'Image',
    icon: cameraSVG,
    group: 'media',
    view: ViewImageBlock,
    edit: EditImageBlock,
    schema: ImageSettingsSchema,
    restricted: false,
    mostUsed: true,
    sidebarTab: 1,
    getSizes: getImageBlockSizes,
  },
  leadimage: {
    id: 'leadimage',
    title: 'Lead Image Field',
    icon: cameraSVG,
    group: 'media',
    view: ViewLeadImageBlock,
    edit: EditLeadImageBlock,
    schema: BlockSettingsSchema,
    restricted: ({ properties }) => !properties.hasOwnProperty('image'),
    mostUsed: false,
    sidebarTab: 1,
    getSizes: getLeadImageBlockSizes,
  },
  listing: {
    id: 'listing',
    title: 'Listing',
    icon: listingBlockSVG,
    group: 'common',
    view: ViewListingBlock,
    edit: EditListingBlock,
    schema: BlockSettingsSchema,
    blockSchema: ListingBlockSchema,
    restricted: false,
    mostUsed: true,
    sidebarTab: 1,
    showLinkMore: false,
    noResultsComponent: DefaultNoResultsComponent,
    variations: [
      {
        id: 'default',
        isDefault: true,
        title: 'Default',
        template: DefaultListingBlockTemplate,
      },
      {
        id: 'imageGallery',
        title: 'Image gallery',
        template: ImageGalleryListingBlockTemplate,
        noResultsComponent: GalleryNoResultsComponent,
      },
      {
        id: 'summary',
        title: 'Summary',
        template: SummaryListingBlockTemplate,
      },
    ],
    getAsyncData: getListingBlockAsyncData,
  },
  video: {
    id: 'video',
    title: 'Video',
    icon: videoSVG,
    group: 'media',
    view: ViewVideoBlock,
    edit: EditVideoBlock,
    schema: BlockSettingsSchema,
    blockSchema: VideoBlockSchema,
    restricted: false,
    mostUsed: true,
    sidebarTab: 1,
    allowedPeertubeInstances: [],
  },
  toc: {
    id: 'toc',
    title: 'Table of Contents',
    icon: tocSVG,
    group: 'common',
    view: ViewToCBlock,
    edit: EditToCBlock,
    schema: ToCSettingsSchema,
    variations: ToCVariations,
    restricted: false,
    mostUsed: false,
    sidebarTab: 1,
  },
  maps: {
    id: 'maps',
    title: 'Maps',
    icon: globeSVG,
    group: 'common',
    view: ViewMapBlock,
    edit: EditMapBlock,
    schema: BlockSettingsSchema,
    restricted: false,
    mostUsed: false,
    sidebarTab: 1,
  },
  html: {
    id: 'html',
    title: 'HTML',
    icon: codeSVG,
    group: 'common',
    view: ViewHTMLBlock,
    edit: EditHTMLBlock,
    schema: BlockSettingsSchema,
    restricted: false,
    mostUsed: false,
    sidebarTab: 0,
  },
  search: {
    id: 'search',
    title: 'Search',
    icon: searchSVG,
    group: 'common',
    view: SearchBlockView,
    edit: SearchBlockEdit,
    blockSchema: SearchBlockSchema,
    restricted: false,
    mostUsed: false,
    sidebarTab: 1,
    variations: [
      {
        id: 'facetsRightSide',
        title: 'Facets on right side',
        view: RightColumnFacets,
        isDefault: true,
      },
      {
        id: 'facetsLeftSide',
        title: 'Facets on left side',
        view: LeftColumnFacets,
        isDefault: false,
      },
      {
        id: 'facetsTopSide',
        title: 'Facets on top',
        view: TopSideFacets,
        isDefault: false,
      },
    ],
    extensions: {
      facetWidgets: {
        rewriteOptions: (name, choices) => {
          return name === 'review_state'
            ? choices.map((opt) => ({
                ...opt,
                label: opt.label.replace(/\[.+\]/, '').trim(),
              }))
            : choices;
        },
        types: [
          {
            id: 'selectFacet',
            title: 'Select',
            view: SelectFacet,
            isDefault: true,
            schemaEnhancer: SelectFacet.schemaEnhancer,
            stateToValue: SelectFacet.stateToValue,
            valueToQuery: SelectFacet.valueToQuery,
            filterListComponent: SelectFacetFilterListEntry,
          },
          {
            id: 'checkboxFacet',
            title: 'Checkbox',
            view: CheckboxFacet,
            isDefault: false,
            schemaEnhancer: CheckboxFacet.schemaEnhancer,
            stateToValue: CheckboxFacet.stateToValue,
            valueToQuery: CheckboxFacet.valueToQuery,
            filterListComponent: SelectFacetFilterListEntry,
          },
          {
            id: 'daterangeFacet',
            title: 'Date Range',
            view: DateRangeFacet,
            isDefault: false,
            stateToValue: DateRangeFacet.stateToValue,
            valueToQuery: DateRangeFacet.valueToQuery,
            filterListComponent: DateRangeFacetFilterListEntry,
          },
          {
            id: 'toggleFacet',
            title: 'Toggle',
            view: ToggleFacet,
            isDefault: false,
            stateToValue: ToggleFacet.stateToValue,
            valueToQuery: ToggleFacet.valueToQuery,
            filterListComponent: ToggleFacetFilterListEntry,
          },
        ],
      },
    },
  },
  // This next block is not named just grid for some reasons:
  // 1.- Naming it grid will collide with the SemanticUI CSS of the Grid component
  // 2.- It would prevent the transition from the old grid
  //     (based on @kitconcept/volto-blocks-grid) without having to perform any migration.
  //     This way, both can co-exist at the same time.
  gridBlock: {
    id: 'gridBlock',
    title: 'Grid',
    icon: gridSVG,
    group: 'common',
    view: GridBlockView,
    edit: GridBlockEdit,
    blockSchema: GridBlockSchema,
    dataAdapter: GridBlockDataAdapter,
    restricted: false,
    mostUsed: true,
    sidebarTab: 1,
    templates: GridTemplates,
    maxLength: 4,
    allowedBlocks: ['image', 'listing', 'slate', 'teaser'],
  },
  teaser: {
    id: 'teaser',
    title: 'Teaser',
    icon: imagesSVG,
    group: 'common',
    view: TeaserViewBlock,
    edit: TeaserEditBlock,
    restricted: false,
    mostUsed: true,
    sidebarTab: 1,
    blockSchema: TeaserSchema,
    dataAdapter: TeaserBlockDataAdapter,
    getSizes: getTeaserBlockSizes,
    variations: [
      {
        id: 'default',
        isDefault: true,
        title: 'Default',
        template: TeaserBlockDefaultBody,
      },
    ],
  },
};

// This is required in order to initialize the inner blocksConfig
// for the grid block, since we need to modify how the inner teaser
// block behave in it (= no schemaEnhancer fields for teasers inside a grid)
// Afterwards, it can be further customized in add-ons using the same technique.
blocksConfig.gridBlock.blocksConfig = cloneDeep(blocksConfig);
blocksConfig.gridBlock.blocksConfig.teaser.schemaEnhancer =
  gridTeaserDisableStylingSchema;
blocksConfig.gridBlock.blocksConfig.image.schemaEnhancer =
  gridImageDisableSizeAndPositionHandlersSchema;

const requiredBlocks = [];

const initialBlocks = {};
const initialBlocksFocus = {}; //{Document:'title'}

export function installDefaultBlocks(config) {
  config.blocks.requiredBlocks = requiredBlocks;
  config.blocks.blocksConfig = blocksConfig;
  config.blocks.groupBlocksOrder = groupBlocksOrder;
  config.blocks.initialBlocks = initialBlocks;
  config.blocks.initialBlocksFocus = initialBlocksFocus;
  config.blocks.showEditBlocksInBabelView = false;
}

export {
  groupBlocksOrder,
  requiredBlocks,
  blocksConfig,
  initialBlocks,
  initialBlocksFocus,
};
