import "core-js/modules/es.array.iterator";
import "core-js/modules/web.dom-collections.iterator";
import _findInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/find";
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
import _objectWithoutPropertiesLoose from "@babel/runtime-corejs3/helpers/objectWithoutPropertiesLoose";
import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
import _Array$isArray from "@babel/runtime-corejs3/core-js-stable/array/is-array";
// @flow
import * as React from 'react';
import isEqual from 'lodash/isEqual';
import createFilterOrig from 'mapeo-entity-filter';
import ObservationDialog from './ObservationDialog';
import getStats from './stats';
import { defaultGetPreset } from './utils/helpers';
/*:: import type { Observation } from 'mapeo-schema'*/

/*:: import type {
  PresetWithFields,
  PresetWithAdditionalFields,
  GetMedia,
  Filter,
  GetIconUrl,
  GetMediaUrl
} from './types'*/

/*:: export type CommonViewProps = {
  /** Array of observations to render *-/
  observations?: Array<Observation>,
  /** Called when an observation is editing/updated *-/
  onUpdateObservation: (observation: Observation) => void,
  onDeleteObservation: (id: string) => void,
  /** A function called with an observation that should return a matching preset
   * with field definitions *-/
  presets?: PresetWithFields[],
  getMediaUrl: GetMediaUrl,
  getIconUrl?: GetIconUrl,
  /** Filter to apply to observations *-/
  filter?: Filter
}*/

/*:: type Props = {
  ...$Exact<CommonViewProps>,
  children: ({
    filteredObservations: Array<Observation>,
    onClickObservation: (observationId: string, imageIndex?: number) => void,
    getPreset: Observation => PresetWithAdditionalFields,
    getMedia: GetMedia
  }) => React.Node
}*/

const noop = () => {}; // This is a temporary wrapper to compile a filter that defines $preset into a
// filter that will work with our dataset, which currently uses categoryId to
// define which preset applies. We will need to improve how this works in the
// future once we start matching presets like we do with iD


const createFilter = (filter
/*: Filter | void*/
) => {
  if (!_Array$isArray(filter) || filter[0] !== 'all' || filter.length < 2) {
    return () => true;
  }

  const presetFilter = _mapInstanceProperty(filter).call(filter, subFilter => {
    if (!_Array$isArray(subFilter) || subFilter[1] !== '$preset' && !isEqual(subFilter[1], ['$preset'])) {
      return subFilter;
    }

    return [subFilter[0], 'categoryId', ..._sliceInstanceProperty(subFilter).call(subFilter, 2)];
  });

  return createFilterOrig(presetFilter);
};

const WrappedMapView = (_ref) => {
  let {
    observations = [],
    onUpdateObservation = noop,
    onDeleteObservation = noop,
    presets = [],
    getMediaUrl,
    filter,
    children
  }
  /*: Props*/
  = _ref,
      otherProps = _objectWithoutPropertiesLoose(_ref, ["observations", "onUpdateObservation", "onDeleteObservation", "presets", "getMediaUrl", "filter", "children"]);

  const stats = React.useMemo(() => getStats(observations), [observations]);
  const [editingObservation, setEditingObservation] = React.useState(null);
  const [editingInitialImageIndex, setEditingInitialImageIndex] = React.useState();
  const getPresetWithFallback = React.useCallback((observation
  /*: Observation*/
  ) =>
  /*: PresetWithAdditionalFields*/
  {
    var _context;

    const preset = getPreset(observation, presets);
    const defaultPreset = defaultGetPreset(observation, stats);
    if (!preset) return defaultPreset;
    return _Object$assign({}, preset, {
      additionalFields: _filterInstanceProperty(_context = defaultPreset.additionalFields).call(_context, // Any fields that are not defined in the preset we show as 'additionalFields'
      additionalField => {
        var _context2;

        return !_findInstanceProperty(_context2 = preset.fields).call(_context2, field => {
          const fieldKey = _Array$isArray(field.key) ? field.key : [field.key];
          const additionalFieldKey = _Array$isArray(additionalField.key) ? additionalField.key : [additionalField.key];
          return isEqual(fieldKey, additionalFieldKey);
        });
      })
    });
  }, [presets, stats]);
  const handleObservationClick = React.useCallback((observationId, imageIndex) => {
    setEditingInitialImageIndex(imageIndex);
    setEditingObservation(_findInstanceProperty(observations).call(observations, obs => obs.id === observationId));
  }, [observations]);
  const getMedia = React.useCallback((attachment, {
    width = 800
  } = {}) => {
    const dpr = window.devicePixelRatio;
    const size = width < 300 * dpr ? 'thumbnail' : width < 1200 * dpr ? 'preview' : 'original';
    return {
      src: getMediaUrl(attachment.id, size),
      type: 'image'
    };
  }, [getMediaUrl]);
  const filterFunction = React.useMemo(() => createFilter(filter), [filter]);
  const filteredObservations = React.useMemo(() => filter ? _filterInstanceProperty(observations).call(observations, filterFunction) : observations, [observations, filterFunction, filter]);
  return /*#__PURE__*/React.createElement(React.Fragment, null, children({
    onClickObservation: handleObservationClick,
    filteredObservations,
    getPreset: getPresetWithFallback,
    getMedia
  }), /*#__PURE__*/React.createElement(ObservationDialog, {
    open: !!editingObservation,
    observation: editingObservation,
    initialImageIndex: editingInitialImageIndex,
    getPreset: getPresetWithFallback,
    getMedia: getMedia,
    onRequestClose: () => setEditingObservation(false),
    onSave: onUpdateObservation,
    onDelete: onDeleteObservation
  }));
};

export default WrappedMapView; // TODO: Update this function to match presets like ID Editor

function getPreset(observation
/*: Observation*/
, presets
/*: PresetWithFields[]*/
)
/*: PresetWithFields | void*/
{
  const tags = observation.tags;
  if (!tags || !tags.categoryId) return;

  const preset = _findInstanceProperty(presets).call(presets, preset => preset.id === tags.categoryId);

  return preset;
}
//# sourceMappingURL=ViewWrapper.js.map