"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _components = require("@wordpress/components");
var _compose = require("@wordpress/compose");
var _i18n = require("@wordpress/i18n");
var _icons = require("@wordpress/icons");
var _context = require("./context");
var _fontCard = _interopRequireDefault(require("./font-card"));
var _filterFonts = _interopRequireDefault(require("./utils/filter-fonts"));
var _toggleFont = require("./utils/toggleFont");
var _fontsOutline = require("./utils/fonts-outline");
var _googleFontsConfirmDialog = _interopRequireDefault(require("./google-fonts-confirm-dialog"));
var _utils = require("./utils");
var _sortFontFaces = require("./utils/sort-font-faces");
var _collectionFontVariant = _interopRequireDefault(require("./collection-font-variant"));
var _jsxRuntime = require("react/jsx-runtime");
/**
 * WordPress dependencies
 */

/**
 * Internal dependencies
 */

const DEFAULT_CATEGORY = {
  slug: 'all',
  name: (0, _i18n._x)('All', 'font categories')
};
const LOCAL_STORAGE_ITEM = 'wp-font-library-google-fonts-permission';
const MIN_WINDOW_HEIGHT = 500;
function FontCollection({
  slug
}) {
  var _selectedCollection$c;
  const requiresPermission = slug === 'google-fonts';
  const getGoogleFontsPermissionFromStorage = () => {
    return window.localStorage.getItem(LOCAL_STORAGE_ITEM) === 'true';
  };
  const [selectedFont, setSelectedFont] = (0, _element.useState)(null);
  const [notice, setNotice] = (0, _element.useState)(false);
  const [fontsToInstall, setFontsToInstall] = (0, _element.useState)([]);
  const [page, setPage] = (0, _element.useState)(1);
  const [filters, setFilters] = (0, _element.useState)({});
  const [renderConfirmDialog, setRenderConfirmDialog] = (0, _element.useState)(requiresPermission && !getGoogleFontsPermissionFromStorage());
  const {
    collections,
    getFontCollection,
    installFonts,
    isInstalling
  } = (0, _element.useContext)(_context.FontLibraryContext);
  const selectedCollection = collections.find(collection => collection.slug === slug);
  (0, _element.useEffect)(() => {
    const handleStorage = () => {
      setRenderConfirmDialog(requiresPermission && !getGoogleFontsPermissionFromStorage());
    };
    handleStorage();
    window.addEventListener('storage', handleStorage);
    return () => window.removeEventListener('storage', handleStorage);
  }, [slug, requiresPermission]);
  const revokeAccess = () => {
    window.localStorage.setItem(LOCAL_STORAGE_ITEM, 'false');
    window.dispatchEvent(new Event('storage'));
  };
  (0, _element.useEffect)(() => {
    const fetchFontCollection = async () => {
      try {
        await getFontCollection(slug);
        resetFilters();
      } catch (e) {
        if (!notice) {
          setNotice({
            type: 'error',
            message: e?.message
          });
        }
      }
    };
    fetchFontCollection();
  }, [slug, getFontCollection, setNotice, notice]);
  (0, _element.useEffect)(() => {
    setSelectedFont(null);
  }, [slug]);
  (0, _element.useEffect)(() => {
    // If the selected fonts change, reset the selected fonts to install
    setFontsToInstall([]);
  }, [selectedFont]);
  const collectionFonts = (0, _element.useMemo)(() => {
    var _selectedCollection$f;
    return (_selectedCollection$f = selectedCollection?.font_families) !== null && _selectedCollection$f !== void 0 ? _selectedCollection$f : [];
  }, [selectedCollection]);
  const collectionCategories = (_selectedCollection$c = selectedCollection?.categories) !== null && _selectedCollection$c !== void 0 ? _selectedCollection$c : [];
  const categories = [DEFAULT_CATEGORY, ...collectionCategories];
  const fonts = (0, _element.useMemo)(() => (0, _filterFonts.default)(collectionFonts, filters), [collectionFonts, filters]);
  const isLoading = !selectedCollection?.font_families && !notice;

  // NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px
  // The height of each font family item is 61px.
  const windowHeight = Math.max(window.innerHeight, MIN_WINDOW_HEIGHT);
  const pageSize = Math.floor((windowHeight - 417) / 61);
  const totalPages = Math.ceil(fonts.length / pageSize);
  const itemsStart = (page - 1) * pageSize;
  const itemsLimit = page * pageSize;
  const items = fonts.slice(itemsStart, itemsLimit);
  const handleCategoryFilter = category => {
    setFilters({
      ...filters,
      category
    });
    setPage(1);
  };
  const handleUpdateSearchInput = value => {
    setFilters({
      ...filters,
      search: value
    });
    setPage(1);
  };
  const debouncedUpdateSearchInput = (0, _compose.debounce)(handleUpdateSearchInput, 300);
  const resetFilters = () => {
    setFilters({});
    setPage(1);
  };
  const handleToggleVariant = (font, face) => {
    const newFontsToInstall = (0, _toggleFont.toggleFont)(font, face, fontsToInstall);
    setFontsToInstall(newFontsToInstall);
  };
  const fontToInstallOutline = (0, _fontsOutline.getFontsOutline)(fontsToInstall);
  const resetFontsToInstall = () => {
    setFontsToInstall([]);
  };
  const selectFontCount = fontsToInstall.length > 0 ? fontsToInstall[0]?.fontFace?.length : 0;

  // Check if any fonts are selected.
  const isIndeterminate = selectFontCount > 0 && selectFontCount !== selectedFont?.fontFace?.length;

  // Check if all fonts are selected.
  const isSelectAllChecked = selectFontCount === selectedFont?.fontFace?.length;

  // Toggle select all fonts.
  const toggleSelectAll = () => {
    const newFonts = isSelectAllChecked ? [] : [selectedFont];
    setFontsToInstall(newFonts);
  };
  const handleInstall = async () => {
    setNotice(null);
    const fontFamily = fontsToInstall[0];
    try {
      if (fontFamily?.fontFace) {
        await Promise.all(fontFamily.fontFace.map(async fontFace => {
          if (fontFace.src) {
            fontFace.file = await (0, _utils.downloadFontFaceAssets)(fontFace.src);
          }
        }));
      }
    } catch (error) {
      // If any of the fonts fail to download,
      // show an error notice and stop the request from being sent.
      setNotice({
        type: 'error',
        message: (0, _i18n.__)('Error installing the fonts, could not be downloaded.')
      });
      return;
    }
    try {
      await installFonts([fontFamily]);
      setNotice({
        type: 'success',
        message: (0, _i18n.__)('Fonts were installed successfully.')
      });
    } catch (error) {
      setNotice({
        type: 'error',
        message: error.message
      });
    }
    resetFontsToInstall();
  };
  const getSortedFontFaces = fontFamily => {
    if (!fontFamily) {
      return [];
    }
    if (!fontFamily.fontFace || !fontFamily.fontFace.length) {
      return [{
        fontFamily: fontFamily.fontFamily,
        fontStyle: 'normal',
        fontWeight: '400'
      }];
    }
    return (0, _sortFontFaces.sortFontFaces)(fontFamily.fontFace);
  };
  if (renderConfirmDialog) {
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_googleFontsConfirmDialog.default, {});
  }
  const ActionsComponent = () => {
    if (slug !== 'google-fonts' || renderConfirmDialog || selectedFont) {
      return null;
    }
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.DropdownMenu, {
      icon: _icons.moreVertical,
      label: (0, _i18n.__)('Actions'),
      popoverProps: {
        position: 'bottom left'
      },
      controls: [{
        title: (0, _i18n.__)('Revoke access to Google Fonts'),
        onClick: revokeAccess
      }]
    });
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
    className: "font-library-modal__tabpanel-layout",
    children: [isLoading && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: "font-library-modal__loading",
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ProgressBar, {})
    }), !isLoading && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Navigator, {
        initialPath: "/",
        className: "font-library-modal__tabpanel-layout",
        children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Navigator.Screen, {
          path: "/",
          children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
            justify: "space-between",
            children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalVStack, {
              children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalHeading, {
                level: 2,
                size: 13,
                children: selectedCollection.name
              }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalText, {
                children: selectedCollection.description
              })]
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(ActionsComponent, {})]
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
            margin: 4
          }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Flex, {
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
              children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.SearchControl, {
                className: "font-library-modal__search",
                value: filters.search,
                placeholder: (0, _i18n.__)('Font name…'),
                label: (0, _i18n.__)('Search'),
                onChange: debouncedUpdateSearchInput,
                __nextHasNoMarginBottom: true,
                hideLabelFromVision: false
              })
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.FlexItem, {
              children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.SelectControl, {
                __nextHasNoMarginBottom: true,
                __next40pxDefaultSize: true,
                label: (0, _i18n.__)('Category'),
                value: filters.category,
                onChange: handleCategoryFilter,
                children: categories && categories.map(category => /*#__PURE__*/(0, _jsxRuntime.jsx)("option", {
                  value: category.slug,
                  children: category.name
                }, category.slug))
              })
            })]
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
            margin: 4
          }), !!selectedCollection?.font_families?.length && !fonts.length && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalText, {
            children: (0, _i18n.__)('No fonts found. Try with a different search term')
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
            className: "font-library-modal__fonts-grid__main",
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
              role: "list",
              className: "font-library-modal__fonts-list",
              children: items.map(font => /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
                className: "font-library-modal__fonts-list-item",
                children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_fontCard.default, {
                  font: font.font_family_settings,
                  navigatorPath: "/fontFamily",
                  onClick: () => {
                    setSelectedFont(font.font_family_settings);
                  }
                })
              }, font.font_family_settings.slug))
            })
          })]
        }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Navigator.Screen, {
          path: "/fontFamily",
          children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.Flex, {
            justify: "flex-start",
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Navigator.BackButton, {
              icon: (0, _i18n.isRTL)() ? _icons.chevronRight : _icons.chevronLeft,
              size: "small",
              onClick: () => {
                setSelectedFont(null);
                setNotice(null);
              },
              label: (0, _i18n.__)('Back')
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalHeading, {
              level: 2,
              size: 13,
              className: "edit-site-global-styles-header",
              children: selectedFont?.name
            })]
          }), notice && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
            children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
              margin: 1
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Notice, {
              status: notice.type,
              onRemove: () => setNotice(null),
              children: notice.message
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
              margin: 1
            })]
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
            margin: 4
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalText, {
            children: (0, _i18n.__)('Select font variants to install.')
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
            margin: 4
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.CheckboxControl, {
            className: "font-library-modal__select-all",
            label: (0, _i18n.__)('Select all'),
            checked: isSelectAllChecked,
            onChange: toggleSelectAll,
            indeterminate: isIndeterminate,
            __nextHasNoMarginBottom: true
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
            spacing: 0,
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
              role: "list",
              className: "font-library-modal__fonts-list",
              children: getSortedFontFaces(selectedFont).map((face, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
                className: "font-library-modal__fonts-list-item",
                children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_collectionFontVariant.default, {
                  font: selectedFont,
                  face: face,
                  handleToggleVariant: handleToggleVariant,
                  selected: (0, _fontsOutline.isFontFontFaceInOutline)(selectedFont.slug, selectedFont.fontFace ? face : null,
                  // If the font has no fontFace, we want to check if the font is in the outline
                  fontToInstallOutline)
                })
              }, `face${i}`))
            })
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalSpacer, {
            margin: 16
          })]
        })]
      }), selectedFont && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Flex, {
        justify: "flex-end",
        className: "font-library-modal__footer",
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
          __next40pxDefaultSize: true,
          variant: "primary",
          onClick: handleInstall,
          isBusy: isInstalling,
          disabled: fontsToInstall.length === 0 || isInstalling,
          accessibleWhenDisabled: true,
          children: (0, _i18n.__)('Install')
        })
      }), !selectedFont && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
        expanded: false,
        className: "font-library-modal__footer",
        justify: "end",
        spacing: 6,
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalHStack, {
          justify: "flex-start",
          expanded: false,
          spacing: 1,
          className: "font-library-modal__page-selection",
          children: (0, _element.createInterpolateElement)((0, _i18n.sprintf)(
          // translators: 1: Current page number, 2: Total number of pages.
          (0, _i18n._x)('<div>Page</div>%1$s<div>of %2$s</div>', 'paging'), '<CurrentPage />', totalPages), {
            div: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
              "aria-hidden": true
            }),
            CurrentPage: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.SelectControl, {
              "aria-label": (0, _i18n.__)('Current page'),
              value: page,
              options: [...Array(totalPages)].map((e, i) => {
                return {
                  label: i + 1,
                  value: i + 1
                };
              }),
              onChange: newPage => setPage(parseInt(newPage)),
              size: "small",
              __nextHasNoMarginBottom: true,
              variant: "minimal"
            })
          })
        }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalHStack, {
          expanded: false,
          spacing: 1,
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
            onClick: () => setPage(page - 1),
            disabled: page === 1,
            accessibleWhenDisabled: true,
            label: (0, _i18n.__)('Previous page'),
            icon: (0, _i18n.isRTL)() ? _icons.next : _icons.previous,
            showTooltip: true,
            size: "compact",
            tooltipPosition: "top"
          }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
            onClick: () => setPage(page + 1),
            disabled: page === totalPages,
            accessibleWhenDisabled: true,
            label: (0, _i18n.__)('Next page'),
            icon: (0, _i18n.isRTL)() ? _icons.previous : _icons.next,
            showTooltip: true,
            size: "compact",
            tooltipPosition: "top"
          })]
        })]
      })]
    })]
  });
}
var _default = exports.default = FontCollection;
//# sourceMappingURL=font-collection.js.map