import { GraphQLObjectType, GraphQLString, GraphQLInputObjectType, GraphQLBoolean } from 'graphql';
import { globalIdField } from 'graphql-relay';

// many locations
const setterLocations = ({
  userId: {
    type: GraphQLString,
    description: 'userId',
  },
  lat: {
    type: GraphQLString,
    description: 'latitude',
  },
  lon: {
    type: GraphQLString,
    description: 'longitude',
  },
});

const getterLocations = {
  ...setterLocations,
  id: globalIdField('Geolocations'),
  userId: {
    ...setterLocations.userId,
    resolve: obj => obj.userId,
  },
  lat: {
    ...setterLocations.lat,
    resolve: obj => obj.latitude,
  },
  lon: {
    ...setterLocations.lon,
    resolve: obj => obj.longitude,
  },
};

const getGeolocationsType = (nodeInterface) => {
  const UserType = new GraphQLObjectType({
    name: 'Geolocations',
    description: 'Geolocations users informations',
    fields: getterLocations,
    interfaces: [nodeInterface],
  });
  return UserType;
};

const getGeolocationsInputType = () => new GraphQLInputObjectType({
  name: 'GeolocationsInput',
  fields: setterLocations,
});

// one location
const setterLocation = ({
  collectionID: {
    type: GraphQLString,
    description: 'id collection',
  },
  key: {
    type: GraphQLString,
    description: 'latitude',
  },
  lat: {
    type: GraphQLString,
    description: 'latitude',
  },
  lon: {
    type: GraphQLString,
    description: 'longitude',
  },
});

const setterLocationOptionals = ({
  fetchCloseUsers: {
    type: GraphQLBoolean,
    description: 'fetch close users in response',
  },
  unit: {
    type: GraphQLString,
    description: 'unit distance: km, m',
  },
  distance: {
    type: GraphQLString,
    description: 'rayon distance to scan',
  },
});

const getterLocation = {
  ...setterLocation,
  id: globalIdField('Geolocations'),
  collectionID: {
    ...setterLocation.collectionID,
    resolve: obj => obj.data.id,
  },
  key: {
    ...setterLocation.key,
    resolve: obj => obj.data.key,
  },
  lat: {
    ...setterLocation.key,
    resolve: obj => obj.data.location[0],
  },
  lon: {
    ...setterLocation.key,
    resolve: obj => obj.data.location[1],
  },
};

const getGeolocationType = (nodeInterface) => {
  const UserType = new GraphQLObjectType({
    name: 'Geolocation',
    description: 'Geolocations user informations',
    fields: getterLocation,
    interfaces: [nodeInterface],
  });
  return UserType;
};

const getGeolocationInputType = () => new GraphQLInputObjectType({
  name: 'GeolocationInput',
  fields: { ...setterLocation, ...setterLocationOptionals },
});

// distance
const setterDistanceLocation = ({
  key: {
    type: GraphQLString,
    description: 'from key',
  },
  foreignKey: {
    type: GraphQLString,
    description: 'to foreignKey',
  },
  distance: {
    type: GraphQLString,
    description: 'distance',
  },
});

const getterDistanceLocation = {
  ...setterDistanceLocation,
  id: globalIdField('Distance'),
  key: {
    ...setterLocation.key,
    resolve: obj => obj.data.x,
  },
  foreignKey: {
    ...setterLocation.key,
    resolve: obj => obj.data.y,
  },
  distance: {
    ...setterLocation.key,
    resolve: obj => obj.data.distance,
  },
};

const getGeolocationsDistanceType = (nodeInterface) => {
  const UserType = new GraphQLObjectType({
    name: 'Distance',
    description: 'Geolocations user informations',
    fields: getterDistanceLocation,
    interfaces: [nodeInterface],
  });
  return UserType;
};

const getGeolocationsDistanceInputType = () => new GraphQLInputObjectType({
  name: 'DistanceInput',
  fields: setterDistanceLocation,
});

export default {
  getGeolocationType,
  getGeolocationInputType,
  getGeolocationsType,
  getGeolocationsInputType,
  getGeolocationsDistanceType,
  getGeolocationsDistanceInputType,
};
