import config from '../config';
import 'whatwg-fetch';

const VIDEO_KEYS = [
  "title",
  "source",
  "project",
  "topic",
  "language",
  "duration",
  "id",
  "date"
];

/*
  Base function to make API calls
  All other API methods will call this internally
  Ideally, this is not to be called from the outside
  See https://858.ma/api for API documentation

  @param {String} action - API action to call
  @param {Object} data - data to send with API call, will be JSON.stringified
  @returns {Promise} - Resolves with data if successful, else throws error.
*/
export function callApi(action, data) {
  let formData = new FormData();
  formData.append('action', action);
  formData.append('data', JSON.stringify(data));
  return fetch(config.apiUrl, {
    method: 'POST',
    body: formData
  })
  .then(response => response.json()) // convert the response to json (instead of response object).
  .then(data => {
    if (data.status.code === 200) {
      return data.data;
    } else {
      throw 'API Error';
      // Status code was not 200
      // We need to do some sort of error handling here
      // Not sure the best way to handle this
    }
  })
}

/*
  Fetch all topics from backend
  @param {Number} startRange - range to start from, defaults to 0
  @param {Number} endRange - range to end at, defaults to 1000
  @returns {Promise<Array>} array of topic objects like: {'name': '<topicName>', 'items': <no_of_items>}
*/
export function fetchAllTopics(startRange=0, endRange=1000) {
  // the object that we need to send to the api
  const data = {
    "query": {
      "conditions": [],
      "operator": "&"
    },
    "range": [startRange, endRange],
    "sort": [{
      "key": "items",
      "operator": "-"
    }],
    "group": "topic"
  };
  return callApi('find', data).then(data => data.items);
}

export function fetchAllMonths(startRange=0, endRange=500) {
  const data = {
    "query": {
      "conditions": [],
      "operator": "&"
    },
    "range": [startRange, endRange],
    "sort": [{
      "key": "items",
      "operator": "-"
    }],
    "group": "month"
  };
  return callApi('find', data).then(data => data.items);
}

export function fetchAllDates(startRange=0, endRange=1000) {
  const data = {
    "query": {
      "conditions": [],
      "operator": "&"
    },
    "range": [startRange, endRange],
    "sort": [{
      "key": "items",
      "operator": "-"
    }],
    "group": "date"
  };
  return callApi('find', data).then(data => data.items);
}

/*
  Fetch videos filtered by key
  @param {String} key - key to filter by - eg. "topic"
  @param {String} value - value to filter by
  @param {Number} startRange - start range
  @param {Number} endRange - end range
  @param {String} sortKey - key to sort by, defaults to "random"
  @returns {Promise<Array>} Promise resolves to array of video objects
*/
export function fetchVideosByX(key, value, startRange, endRange, sortKey='random') {
  const data = {
    "keys": VIDEO_KEYS,
    "query": {
      "conditions": [{
        "key": key,
        "value": value,
        "operator": "=="
      }],
      "operator": "&"
    },
    "range": [startRange, endRange],
    "sort": [{
      "key": sortKey,
      "operator": "-"
    }]
  };
  return callApi('find', data).then(data => data.items);
}

/*
  Fetch videos filtered by topic
  @param {String} topic - topic to filter by
  @param {Number} startRange - start range
  @param {Number} endRange - end range
  @param {String} sortKey - key to sort by, defaults to "random"
  @returns {Promise<Array>} Promise resolves to array of video objects
*/
export function fetchVideosByTopic(topic, startRange=0, endRange=100, sortKey='random') {
  return fetchVideosByX('topic', topic, startRange, endRange, sortKey);
};

/*
  month eg. "2011-11"
*/
export function fetchVideosByMonth(month, startRange=0, endRange=100, sortKey='random') {
  return fetchVideosByX('month', month, startRange, endRange, sortKey);
}

/*
  date eg. "2011-11-01"
*/
export function fetchVideosByDate(date, startRange=0, endRange=100, sortKey='random') {
  return fetchVideosByX('date', date, startRange, endRange, sortKey);
}


/*
  Fetch places within bounding box

  @param {Float} north - latitude of north bounds
  @param {Float} south - latitude of south bounds
  @param {Float} west - longitude of west bounds
  @param {Float} east - longitude of east bounds
*/
export function fetchPlaces(north, south, west, east, startRange=0, endRange=100) {
  const data = {
    "itemsQuery": {
      "conditions": [],
      "operator": "&"
    },
    "keys": ["id", "name", "alternativeNames", "geoname", "countryCode", "type", "lat", "lng", "south", "west", "north", "east", "area", "editable"],
    "query": {
      "conditions": [{
        "key": "lat",
        "value": [south, north],
        "operator": "="
      }, {
        "key": "lng",
        "value": [west, east],
        "operator": "="
      }],
      "operator": "&"
    },
    "range": [startRange, endRange],
    "sort": [{
      "key": "area",
      "operator": "-"
    }]
  };
  return callApi('findPlaces', data).then(data => data.items);
}

/*
  Fetches a random place
*/
export function fetchRandomPlace() {
  const data = {
    "itemsQuery": {
      "conditions": [],
      "operator": "&"
    },
    "keys": ["id", "name", "alternativeNames", "geoname", "countryCode", "type", "lat", "lng", "south", "west", "north", "east", "area", "editable"],
    "query": {
      "conditions": [],
      "operator": "&"
    },
    "range": [0, 1],
    "sort": [{
      "key": "random",
      "operator": "-"
    }]
  };
  return callApi('findPlaces', data).then(data => data.items[0]);
}

export function fetchVideosByPlace(placeId, startRange=0, endRange=100, sortKey='random') {
  return fetchVideosByX('place', placeId, startRange, endRange, sortKey);
}

export function fetchVideoById(id) {
  return callApi('get', {'id': id, keys: VIDEO_KEYS});
}
