Source: app/selectors/foodRangeSelectors.js

import intersection from 'lodash/intersection';
import { createSelector } from 'reselect';
import {
  API_STATIC_PUBLIC_ICELAND_LANDING,
  API_STATIC_PUBLIC_ICELAND_OUR_RANGE,
} from 'common/src/app/data/apiStatics';
import compositeInputFormatters from 'common/src/app/enhanced-redux-form/compositeInputFormatters';
import { staticPageSelector } from 'common/src/app/selectors/publicSelectors';
import { availableFlags } from 'common/src/app/util/bitwiseUtils';
import FoodRangeFlags from 'common/src/app/data/enum/FoodRangeFlags';
import { makeEntitySelector } from 'common/src/app/reducers/view/entityViewReducer';

export const getFoodRangeCharacteristics = products =>
  products?.reduce((acc, cur) => {
    acc.push(cur.characteristics);
    return acc;
  }, []);

export const foodRangeNavigation = categories =>
  categories &&
  categories.reduce((acc, cur) => {
    acc[cur.title] = { tabLink: cur.slug }; // eslint-disable-line
    return acc;
  }, {});

export const icelandLandingSelector = state =>
  staticPageSelector(state, API_STATIC_PUBLIC_ICELAND_LANDING);

export const foodRangeCategoriesSelector = state => {
  const entitySelector = makeEntitySelector();
  return entitySelector(state, state.view.pages.foodRangeDetail?.foodRange);
};

export const selectCurrentCategory = (results, routeParams) =>
  results && results.categories.filter(cat => cat.slug === routeParams.category)[0];

/**
 * Returns selected categories
 *
 * @param foodRangeData
 * @param queryCategories
 * @returns {*}
 */
export const selectedFoodRangeCategories = (foodRangeData, queryCategories) =>
  queryCategories &&
  foodRangeData?.categories.filter(cat => queryCategories.split(',').includes(cat.slug));

/**
 * Returns selected categories products or the full products
 *
 * @param queryCategories
 * @returns {*}
 */
export const selectedFoodRangeProducts = queryCategories =>
  createSelector(
    state => foodRangeCategoriesSelector(state),
    foodRangeData => {
      const selectedCategories = selectedFoodRangeCategories(foodRangeData, queryCategories);
      const categories = selectedCategories || foodRangeData?.categories;
      return categories?.reduce((acc, cat) => acc.concat(cat.products), []);
    },
  );

export const filterProducts = (products, filters) => {
  const filtersArray = Object.values(filters);
  if (filtersArray.length === 0) {
    return products;
  }
  return products?.filter(
    product =>
      intersection(
        Object.values(availableFlags([product.characteristics], FoodRangeFlags)),
        filtersArray,
      ).length > 0 && product,
  );
};

export const foodRangeFilterFlagsSelector = queryCategories =>
  createSelector(
    state => staticPageSelector(state, API_STATIC_PUBLIC_ICELAND_OUR_RANGE),
    state => selectedFoodRangeProducts(queryCategories)(state),
    (pageData, foodRangeProducts) => {
      const reduceCharacteristics =
        foodRangeProducts && getFoodRangeCharacteristics(foodRangeProducts);
      const foodRangeDiet =
        reduceCharacteristics && availableFlags(reduceCharacteristics, FoodRangeFlags);

      const categories = pageData?.categories?.reduce(
        (acc, cat, index) =>
          Object.assign(acc, {
            [index]: {
              title: cat.title,
              slug: cat.slug,
            },
          }),
        {
          // add optional formatter
          formatter: compositeInputFormatters.CHECKBOXES_TO_COMMA_DELIMITED_STRING,
          rawDescription: true,
        },
      );

      return {
        ...(categories && { categories }),
        ...(foodRangeDiet && { foodRangeDiet }),
      };
    },
  );

export const foodRangeProductsSelector = (queryCategories, currentFiltersDiet) =>
  createSelector(
    state => selectedFoodRangeProducts(queryCategories)(state),
    foodRangeProducts => filterProducts(foodRangeProducts, currentFiltersDiet),
  );