import "core-js/modules/es.array.iterator";
import "core-js/modules/web.dom-collections.iterator";
import _Object$entries from "@babel/runtime-corejs3/core-js-stable/object/entries";
import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
import _valuesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/values";
import _keysInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/keys";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
import _sortInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/sort";
import _reduceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/reduce";
import _JSON$stringify from "@babel/runtime-corejs3/core-js-stable/json/stringify";
// @flow
import * as valueTypes from '../../constants/value_types';
import { guessValueType } from './value_types';
import { flatObjectEntries } from '../../utils/flat_object_entries';
import { get } from '../../utils/get_set';
/*:: import type {
  JSONObject,
  FieldStatistic,
  Statistics,
  MediaArray,
  Field,
  TextField,
  LinkField,
  NumberField,
  DateField,
  DateTimeField,
  SelectOptions,
  SelectOneField,
  SelectMultipleField
} from '../../types'*/

export { default as createMemoizedStats } from './statistics';
const mediaTypes = [valueTypes.VIDEO_URL, valueTypes.AUDIO_URL, valueTypes.IMAGE_URL];

function compareKeys(a, b) {
  return _JSON$stringify(a[0]).localeCompare(_JSON$stringify(b[0]));
}
/**
 * Takes a JSON object and optional array of JSON objects and returns an array
 * of field definitions. The field definitions are guessed from the arguments
 * passed. The returned field definitions can be used to render fields for
 * editing the properties of the object.
 */


export function getFields(cur
/*:: ?: JSONObject*/
= {}, stats
/*:: ?: Statistics*/
)
/*: Array<Field>*/
{
  var _context;

  const entries = stats ? flatStatsEntries(stats) : flatObjectEntries(cur);
  return _reduceInstanceProperty(_context = _sortInstanceProperty(entries).call(entries, compareKeys)).call(_context, (acc, [keyArray]) => {
    const key = _JSON$stringify(keyArray);

    const value = get(cur, keyArray);
    const fieldStats = stats && stats[key];
    const field = getField(keyArray, value, fieldStats);
    if (field) acc.push(field);
    return acc;
  }, []);
}
export function getMedia(cur
/*: JSONObject*/
= {})
/*: MediaArray*/
{
  var _context2;

  return _reduceInstanceProperty(_context2 = flatObjectEntries(cur)).call(_context2, (acc, [keyArray, value]) => {
    const type = guessValueType(value);

    if (_includesInstanceProperty(mediaTypes).call(mediaTypes, type)) {
      // $FlowFixMe flow does not understand type is only media type here
      acc.push({
        src: value,
        type
      });
    }

    return acc;
  }, []);
}
export function getField(keyArray
/*: Array<string | number>*/
, value
/*: any*/
, fieldStats
/*:: ?: FieldStatistic*/
)
/*: Field*/
{
  const valueType = guessValueType(value); // Initial implementation does not try to guess from statistics

  switch (valueType) {
    case valueTypes.BOOLEAN:
      return createSelectOneField(keyArray, [true, false]);

    case valueTypes.STRING:
      {
        const options = getOptions(fieldStats);
        if (options.length) return createSelectOneField(keyArray, options);else return createTextField(keyArray);
      }

    case valueTypes.NUMBER:
      return createNumberField(keyArray);

    case valueTypes.ARRAY:
      {
        const options = getOptions(fieldStats);
        return createSelectMultipleField(keyArray, options.length ? options : value, {
          readonly: true
        });
      }

    case valueTypes.DATE:
      return createDateField(keyArray, {
        min: fieldStats && fieldStats.date.min,
        max: fieldStats && fieldStats.date.max
      });

    case valueTypes.DATETIME:
      return createDateTimeField(keyArray, {
        min: fieldStats && fieldStats.date.min,
        max: fieldStats && fieldStats.date.max
      });

    case valueTypes.URL:
    case valueTypes.IMAGE_URL:
    case valueTypes.AUDIO_URL:
    case valueTypes.VIDEO_URL:
      return createLinkField(keyArray);

    default:
      return createTextField(keyArray, {
        readonly: true
      });
  }
} // Don't include long strings in the options that can be selected

const MAX_OPTION_LENGTH = 30;

function getOptions(fieldStats
/*:: ?: FieldStatistic*/
)
/*: SelectOptions*/
{
  const options = [];
  if (!fieldStats) return options;

  for (const value of _keysInstanceProperty(_context3 = _valuesInstanceProperty(fieldStats.string)).call(_context3)) {
    var _context3;

    if (value.length > MAX_OPTION_LENGTH) continue;
    options.push(value);
  }

  return options;
}

function createTextField(keyArray
/*: Array<string | number>*/
, {
  readonly = false,
  appearance = 'single',
  snakeCase = false
}
/*: {
    readonly?: boolean,
    appearance?: 'single' | 'multiline',
    snakeCase?: boolean
  }*/
= {})
/*: TextField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    appearance: appearance,
    type: 'text'
  };
}

function createLinkField(keyArray
/*: Array<string | number>*/
)
/*: LinkField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: true,
    type: 'link'
  };
}

function createNumberField(keyArray
/*: Array<string | number>*/
, {
  readonly = false
}
/*: { readonly?: boolean }*/
= {})
/*: NumberField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    type: 'number'
  };
}

function createSelectOneField(keyArray
/*: Array<string | number>*/
, options
/*: SelectOptions*/
, {
  readonly = false,
  snakeCase = false
}
/*: { readonly?: boolean, snakeCase?: boolean }*/
= {})
/*: SelectOneField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    type: 'select_one',
    options: options
  };
}

function createSelectMultipleField(keyArray
/*: Array<string | number>*/
, options
/*: SelectOptions*/
, {
  readonly = false,
  snakeCase = false
}
/*: { readonly?: boolean, snakeCase?: boolean }*/
= {})
/*: SelectMultipleField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    type: 'select_multiple',
    options: options
  };
}

function createDateField(keyArray
/*: Array<string | number>*/
, {
  readonly = false,
  min,
  max
}
/*: {
    readonly?: boolean,
    snakeCase?: boolean,
    min?: string,
    max?: string
  }*/
= {})
/*: DateField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    type: 'date',
    min_value: min,
    max_value: max
  };
}

function createDateTimeField(keyArray
/*: Array<string | number>*/
, {
  readonly = false,
  min,
  max
}
/*: {
    readonly?: boolean,
    snakeCase?: boolean,
    min?: string,
    max?: string
  }*/
= {})
/*: DateTimeField*/
{
  return {
    id: _JSON$stringify([...arguments]),
    key: keyArray,
    readonly: readonly,
    type: 'datetime',
    min_value: min,
    max_value: max
  };
}

function flatStatsEntries(stats
/*: Statistics*/
)
/*: Array<[Array<string | number>, FieldStatistic]>*/
{
  var _context4;

  // $FlowFixMe
  return _mapInstanceProperty(_context4 = _Object$entries(stats)).call(_context4, ([key, value]) => [JSON.parse(key), value]);
}
//# sourceMappingURL=index.js.map