const createIdFilters = require('./filters/idFilters')
const createStringFilters = require('./filters/stringFilters')
const createFloatFilters = require('./filters/floatFilters')
const createIntegerFilters = require('./filters/integerFilters')
const createBooleanFilters = require('./filters/booleanFilters')
const createDatetimeFilters = require('./filters/datetimeFilters')
const createDateFilters = require('./filters/dateFilters')
const createDocumentFilters = require('./filters/documentFilters')

const typeAliases = {
  Url: 'String',
  Text: 'String',
  Email: 'String'
}

const filterCreators = {
  ID: createIdFilters,
  String: createStringFilters,
  Float: createFloatFilters,
  Integer: createIntegerFilters,
  Boolean: createBooleanFilters,
  Datetime: createDatetimeFilters,
  Date: createDateFilters,
  Document: createDocumentFilters
}

function generateTypeFilters(types) {
  const builtInTypeKeys = Object.keys(filterCreators)
  const builtinTypeValues = Object.values(filterCreators)
  const objectTypes = types.filter(
    type =>
      type.type === 'Object' &&
      !['Block', 'Span'].includes(type.name) && // TODO: What do we do with blocks?
      !type.interfaces &&
      !builtInTypeKeys.includes(type.type)
  )

  const unionTypes = types.filter(type => type.kind === 'Union').map(type => type.name)
  const documentTypes = types.filter(
    type => type.type === 'Object' && type.interfaces && type.interfaces.includes('Document')
  )

  const builtinTypeFilters = createBuiltinTypeFilters(builtinTypeValues)
  const objectTypeFilters = createObjectTypeFilters(objectTypes, {unionTypes})
  const documentTypeFilters = createDocumentTypeFilters(documentTypes, {unionTypes})

  return builtinTypeFilters.concat(objectTypeFilters).concat(documentTypeFilters)
}

function createBuiltinTypeFilters(builtinTypeValues) {
  return builtinTypeValues.map(filterCreator => filterCreator())
}

function createObjectTypeFilters(objectTypes, options) {
  return objectTypes.map(objectType => {
    return {
      name: `${objectType.name}Filter`,
      kind: 'InputObject',
      fields: createFieldFilters(objectType, options)
    }
  })
}

function createDocumentTypeFilters(documentTypes, options) {
  return documentTypes.map(documentType => {
    const fields = getDocumentFilters().concat(createFieldFilters(documentType, options))
    return {
      name: `${documentType.name}Filter`,
      kind: 'InputObject',
      fields
    }
  })
}

function createFieldFilters(objectType, options) {
  const {unionTypes} = options
  return objectType.fields
    .filter(
      field => field.type !== 'JSON' && field.kind !== 'List' && !unionTypes.includes(field.type)
    )
    .map(field => ({
      fieldName: field.fieldName,
      type: `${typeAliases[field.type] || field.type}Filter`,
      isReference: field.isReference
    }))
}

function getDocumentFilters() {
  return [
    {
      fieldName: '_',
      type: 'DocumentFilter',
      description: 'Apply filters on document level'
    }
  ]
}

module.exports = generateTypeFilters

@@ -1,26 +1,31 @@
 const create
-Id
+Boolean
 Filters = re
@@ -45,10 +45,15 @@
 ers/
-id
+boolean
 Filt
@@ -74,49 +74,179 @@
 eate
-StringFilters = require('./filters/string
+DateFilters = require('./filters/dateFilters')%0Aconst createDatetimeFilters = require('./filters/dateTimeFilters')%0Aconst createDocumentFilters = require('./filters/document
 Filt
@@ -304,32 +304,87 @@
 /floatFilters')%0A
+const createIdFilters = require('./filters/idFilters')%0A
 const createInte
@@ -448,244 +448,49 @@
 eate
-BooleanFilters = require('./filters/booleanFilters')%0Aconst createDatetimeFilters = require('./filters/datetimeFilters')%0Aconst createDateFilters = require('./filters/dateFilters')%0Aconst createDocumentFilters = require('./filters/document
+StringFilters = require('./filters/string
 Filt

Fix incorrect filename casing on import statement