import {
  Field as FieldModel,
  FieldType,
} from '@airtable/blocks/models';
import { isNil } from 'lodash';

import {
  AirtableModelAttributes,
  SerializedModelProperties,
} from './AirtableModel';

type UserFriendlyFieldDescription = Readonly<{
  description: string;
  options?: Readonly<{
    description: string;
    value: string | boolean;
  }[]>;
}>;

/**
 * Airtable fields are presented differently to the user. This data structure provides enough information for the user to change a field's type based on the descriptions they're presented.
 */
export const FieldTypeToDescription:Record<FieldType, UserFriendlyFieldDescription> = {
  [FieldType.SINGLE_LINE_TEXT]: {
    description: 'Single line text'
  },
  [FieldType.EMAIL]: {
    description: 'Email'
  },
  [FieldType.URL]: {
    description: 'URL'
  },
  [FieldType.MULTILINE_TEXT]: {
    description: 'Long text',
    options: [{
      description: 'Disable rich text formatting',
      value: true
    }]
  },
  [FieldType.NUMBER]: {
    description: 'Number',
  },
  [FieldType.PERCENT]: {
    description: 'Percent'
  },
  [FieldType.CURRENCY]: {
    description: 'Currency'
  },
  [FieldType.SINGLE_SELECT]: {
    description: 'Single select'
  },
  [FieldType.MULTIPLE_SELECTS]: {
    description: 'Multiple select'
  },
  [FieldType.SINGLE_COLLABORATOR]: {
    description: 'Collaborator',
    options: [{
      description: 'Allow adding multiple collaborators',
      value: false,
    }]
  },
  [FieldType.MULTIPLE_COLLABORATORS]: {
    description: 'Collaborator',
    options: [{
      description: 'Allow adding multiple collaborators',
      value: true,
    }]
  },
  [FieldType.MULTIPLE_RECORD_LINKS]: {
    description: 'Link to another record',
  },
  [FieldType.DATE]: {
    description: 'Date',
    options: [{
      description: 'Include a time field',
      value: false,
    }]
  },
  [FieldType.DATE_TIME]: {
    description: 'Date',
    options: [{
      description: 'Include a time field',
      value: true,
    }]
  },
  [FieldType.PHONE_NUMBER]: {
    description: 'Phone number',
  },
  [FieldType.MULTIPLE_ATTACHMENTS]: {
    description: 'Attachment'
  },
  [FieldType.CHECKBOX]: {
    description: 'Checkbox'
  },
  [FieldType.FORMULA]: {
    description: 'Formula'
  },
  [FieldType.CREATED_TIME]: {
    description: 'Created time'
  },
  [FieldType.ROLLUP]: {
    description: 'Rollup'
  },
  [FieldType.COUNT]: {
    description: 'Count'
  },
  [FieldType.MULTIPLE_LOOKUP_VALUES]: {
    description: 'Lookup'
  },
  [FieldType.AUTO_NUMBER]: {
    description: 'Autonumber'
  },
  [FieldType.BARCODE]: {
    description: 'Barcode',
  },
  [FieldType.RATING]: {
    description: 'Barcode',
  },
  [FieldType.RICH_TEXT]: {
    description: 'Long text',
    options: [{
      description: 'Disable rich text formatting',
      value: false
    }]
  },
  [FieldType.DURATION]: {
    description: 'Duration'
  },
  [FieldType.LAST_MODIFIED_TIME]: {
    description: 'Last modified time'
  },
  [FieldType.CREATED_BY]: {
    description: 'Created by'
  },
  [FieldType.LAST_MODIFIED_BY]: {
    description: 'Last modified by'
  },
  [FieldType.BUTTON]: {
    description: 'Button'
  },
  [FieldType.EXTERNAL_SYNC_SOURCE]: {
    // TODO: I can't find this field description...
    description: 'External Sync Source'
  }
} as const;

const SerializedFieldProperties = [...SerializedModelProperties, 'name', 'type', 'options'] as const;
export type SerializedAirtableField = AirtableModelAttributes<FieldModel, SerializedFieldProperties>;
type SerializedFieldProperties = typeof SerializedFieldProperties[number];

export function serializeField(airtableField: FieldModel): SerializedAirtableField {
  return SerializedFieldProperties.reduce((accum:SerializedAirtableField, propertyName:SerializedFieldProperties) => {

    // SINGLE_SELECT and MULTIPLE_SELECTS fields may have lots of choices (up to 10,000).
    // It takes a lot of bandwidth to sync this data that really has no use on our end.
    // Let Airtable handle generating choices objects. Field ids and names are more important.
    if (propertyName === 'options' && !isNil(airtableField['options'])) {
      const options = airtableField[propertyName];
      const { choices, ...restOptions } = options!;

      (accum as any)[propertyName] = restOptions;

      return accum;
    }

    (accum as any)[propertyName] = airtableField[propertyName];

    return accum;
  }, {} as SerializedAirtableField);
}
