
'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.fetchTaggedArticlesIfNeeded = fetchTaggedArticlesIfNeeded;
exports.fetchCategorizedArticlesIfNeeded = fetchCategorizedArticlesIfNeeded;

var _normalizr = require('normalizr');

var _index = require('../schemas/index');

var _humps = require('humps');

var _index2 = require('../utils/index');

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _index3 = require('../constants/index');

var CONSTANTS = _interopRequireWildcard(_index3);

var _isomorphicFetch = require('isomorphic-fetch');

var _isomorphicFetch2 = _interopRequireDefault(_isomorphicFetch);

var _groups = require('./groups');

var _qs = require('qs');

var _qs2 = _interopRequireDefault(_qs);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var groupEnum = CONSTANTS.groupEnum;

function requestArticles(groupType, groupNames) {
  var type = groupType === groupEnum.CATEGORY ? CONSTANTS.FETCH_ARTICLES_BY_CATS_REQUEST : CONSTANTS.FETCH_ARTICLES_BY_TAGS_REQUEST;
  return {
    type: type,
    groups: groupNames
  };
}

function failToReceiveArticles(groupType, groupNames, error) {
  var type = groupType === groupEnum.CATEGORY ? CONSTANTS.FETCH_ARTICLES_BY_CATS_FAILURE : CONSTANTS.FETCH_ARTICLES_BY_TAGS_FAILURE;
  return {
    type: type,
    groups: groupNames,
    error: error,
    failedAt: Date.now()
  };
}

function receiveArticles(groupType, groupNames, response) {
  var type = groupType === groupEnum.CATEGORY ? CONSTANTS.FETCH_ARTICLES_BY_CATS_SUCCESS : CONSTANTS.FETCH_ARTICLES_BY_TAGS_SUCCESS;
  return {
    type: type,
    groups: groupNames,
    response: response,
    receivedAt: Date.now()
  };
}

function fetchArticles(groupType) {
  var groupNames = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
  var url = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2];

  return function (dispatch) {
    dispatch(requestArticles(groupType, groupNames));
    return (0, _isomorphicFetch2.default)(url).then(function (response) {
      if (response.status >= 400) {
        throw new Error('Bad response from API');
      }
      return response.json();
    }).then(function (response) {
      var camelizedJson = (0, _humps.camelizeKeys)(response);
      var normalized = (0, _normalizr.normalize)(camelizedJson.items, (0, _normalizr.arrayOf)(_index.article));
      dispatch(receiveArticles(groupType, groupNames, (0, _lodash.merge)(normalized, { links: camelizedJson.links, meta: camelizedJson.meta })));
    }, function (error) {
      dispatch(failToReceiveArticles(groupType, groupNames, error));
    });
  };
}

function buildQueryURL(groupType) {
  var groupIds = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
  var count = arguments.length <= 2 || arguments[2] === undefined ? 10 : arguments[2];
  var page = arguments.length <= 3 || arguments[3] === undefined ? 1 : arguments[3];

  var query = {};
  var where = {};
  if (groupIds.length !== 0) {
    var group = groupType === groupEnum.CATEGORY ? 'categories' : 'tags';
    where[group] = {
      '$in': groupIds
    };
  } else {
    return new Error('There is no tag/category ids to build query');
  }
  query.where = JSON.stringify(where);
  query.max_results = count || 10;
  query.page = page || 0;
  query.sort = '-publishedDate';
  query.embedded = JSON.stringify((0, _index2.getArticleEmbeddedQuery)());
  query = _qs2.default.stringify(query);
  return (0, _index2.formatUrl)('posts?' + query);
}

function getNextUrl() {
  var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  var groupType = arguments[1];
  var groupNames = arguments.length <= 2 || arguments[2] === undefined ? [] : arguments[2];
  var count = arguments.length <= 3 || arguments[3] === undefined ? 10 : arguments[3];
  var page = arguments.length <= 4 || arguments[4] === undefined ? 1 : arguments[4];

  var existedArticles = void 0;
  var existedGroups = void 0;
  if (groupType === groupEnum.CATEGORY) {
    existedArticles = state.articlesByCats;
    existedGroups = state.categories;
  } else if (groupType === groupEnum.TAG) {
    existedArticles = state.articlesByTags;
    existedGroups = state.tags;
  } else {
    return null;
  }

  groupNames = Array.isArray(groupNames) ? groupNames : [groupNames];
  var groupNameStr = groupNames.join();
  var articles = _lodash2.default.get(existedArticles, [groupNameStr]);
  if (articles) {
    // articles are already loaded
    if (articles.items.length >= count * page) {
      return null;
    }
    return existedArticles[groupNameStr].nextUrl;
  }

  // for the first time to get the articles
  // build the query string
  var groupIds = [];
  // get group ids by group name from state
  groupNames.forEach(function (groupName) {
    var id = _lodash2.default.get(existedGroups, [groupName, 'id']);
    if (id) {
      groupIds.push(id);
    }
  });
  return buildQueryURL(groupType, groupIds, count, page);
}

function fetchArticlesIfNeeded(groupType, groupNames, count, page) {
  return function (dispatch, getState) {
    var fetchGroup = void 0;
    if (groupType === groupEnum.CATEGORY) {
      fetchGroup = _groups.fetchCategoriesIfNeeded;
    } else if (groupType === groupEnum.TAG) {
      fetchGroup = _groups.fetchTagsIfNeeded;
    } else {
      return dispatch(failToReceiveArticles(groupType, groupNames, new Error('group type should be tag or category')));
    }

    // load group ids by group names
    return dispatch(fetchGroup(groupNames)).then(function () {
      var nextUrl = getNextUrl(getState(), groupType, groupNames, count, page);
      if (nextUrl instanceof Error) {
        // dispatch fail action
        return dispatch(failToReceiveArticles(groupType, groupNames, nextUrl));
      } else if (nextUrl) {
        return dispatch(fetchArticles(groupType, groupNames, nextUrl));
      } else {
        // if nextUrl is null or '', then it means no more to load
        return Promise.resolve();
      }
    });
  };
}

function fetchTaggedArticlesIfNeeded(tags, count, page) {
  return function (dispatch) {
    return dispatch(fetchArticlesIfNeeded(groupEnum.TAG, tags, count, page));
  };
}

function fetchCategorizedArticlesIfNeeded(categories, count, page) {
  return function (dispatch) {
    return dispatch(fetchArticlesIfNeeded(groupEnum.CATEGORY, categories, count, page));
  };
}