'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;}; // Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.




// import { IconCache } from '@parity/ui';
exports.














setTokens = setTokens;exports.





















































loadTokens = loadTokens;exports.

















loadTokensBasics = loadTokensBasics;exports.
























































fetchTokens = fetchTokens;var _lodash = require('lodash');var _store = require('store');var _store2 = _interopRequireDefault(_store);var _config = require('../../config');var _contracts = require('../../contracts');var _contracts2 = _interopRequireDefault(_contracts);var _tokens = require('../../util/tokens');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}var TOKENS_CACHE_LS_KEY_PREFIX = '_parity::tokens::';var log = (0, _config.getLogger)(_config.LOG_KEYS.Balances);function _setTokens(tokens) {return { type: 'setTokens', tokens: tokens };}function setTokens(nextTokens) {return function (dispatch, getState) {var _getState = getState(),api = _getState.api,nodeStatus = _getState.nodeStatus,prevTokens = _getState.tokens;var _Contracts$get = _contracts2.default.get(api),tokenReg = _Contracts$get.tokenReg;var tokens = _extends({}, prevTokens, nextTokens);return tokenReg.getContract().then(function (tokenRegContract) {var lsKey = TOKENS_CACHE_LS_KEY_PREFIX + nodeStatus.netChain;_store2.default.set(lsKey, { tokenreg: tokenRegContract.address, tokens: tokens });}).catch(function (error) {console.error(error);}).then(function () {dispatch(_setTokens(nextTokens));});};}function loadCachedTokens(tokenRegContract) {return function (dispatch, getState) {var _getState2 = getState(),nodeStatus = _getState2.nodeStatus;var lsKey = TOKENS_CACHE_LS_KEY_PREFIX + nodeStatus.netChain;var cached = _store2.default.get(lsKey);if (cached) {// Check if we have data from the right contract
      if (cached.tokenreg === tokenRegContract.address && cached.tokens) {log.debug('found cached tokens', cached.tokens);dispatch(_setTokens(cached.tokens)); // Fetch all the tokens images on load
        // (it's the only thing that might have changed)
        var tokenIndexes = Object.values(cached.tokens).filter(function (t) {return t && t.fetched;}).map(function (t) {return t.index;});fetchTokensData(tokenRegContract, tokenIndexes)(dispatch, getState);} else {_store2.default.remove(lsKey);}}};}function loadTokens() {var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};log.debug('loading tokens', Object.keys(options).length ? options : '');return function (dispatch, getState) {var _Contracts$get2 = _contracts2.default.get(),tokenReg = _Contracts$get2.tokenReg;return tokenReg.getContract().then(function (tokenRegContract) {loadCachedTokens(tokenRegContract)(dispatch, getState);return (0, _tokens.fetchTokenIds)(tokenRegContract.instance);}).then(function (tokenIndexes) {return loadTokensBasics(tokenIndexes, options)(dispatch, getState);}).catch(function (error) {console.warn('tokens::loadTokens', error);});};}function loadTokensBasics(_tokenIndexes, options) {var limit = 64;return function (dispatch, getState) {var _getState3 = getState(),api = _getState3.api,tokens = _getState3.tokens;var _Contracts$get3 = _contracts2.default.get(),tokenReg = _Contracts$get3.tokenReg;var nextTokens = {};var prevTokensIndexes = Object.values(tokens).map(function (t) {return t.index;}); // Only fetch tokens we don't have yet
    var tokenIndexes = _tokenIndexes.filter(function (tokenIndex) {return !prevTokensIndexes.includes(tokenIndex);}).sort();var count = tokenIndexes.length;log.debug('loading basic tokens', tokenIndexes);if (count === 0) {return Promise.resolve();}return tokenReg.getContract().then(function (tokenRegContract) {var promise = Promise.resolve();var first = tokenIndexes[0];var last = tokenIndexes[tokenIndexes.length - 1];var _loop = function _loop(from) {// No need to fetch `limit` elements
        var lowerLimit = Math.min(limit, last - from + 1);promise = promise.then(function () {return (0, _tokens.fetchTokensBasics)(api, tokenRegContract, from, lowerLimit);}).then(function (results) {results.forEach(function (token) {nextTokens[token.id] = token;});});};for (var from = first; from <= last; from += limit) {_loop(from);}return promise;}).then(function () {log.debug('fetched tokens basic info', nextTokens);dispatch(setTokens(nextTokens));}).catch(function (error) {console.warn('tokens::fetchTokens', error);});};}function fetchTokens(_tokenIndexes) {var tokenIndexes = (0, _lodash.uniq)(_tokenIndexes || []);var tokenChunks = (0, _lodash.chunk)(tokenIndexes, 64);return function (dispatch, getState) {var _Contracts$get4 = _contracts2.default.get(),tokenReg = _Contracts$get4.tokenReg;

    return tokenReg.getContract().
    then(function (tokenRegContract) {
      var promise = Promise.resolve();

      tokenChunks.forEach(function (tokenChunk) {
        promise = promise.
        then(function () {return fetchTokensData(tokenRegContract, tokenChunk)(dispatch, getState);});
      });

      return promise;
    }).
    then(function () {
      log.debug('fetched token', getState().tokens);
    }).
    catch(function (error) {
      console.warn('tokens::fetchTokens', error);
    });
  };
}

/**
   * Split the given token indexes between those for whom
   * we already have some info, and thus just need to fetch
   * the image, and those for whom we don't have anything and
   * need to fetch all the info.
   */
function fetchTokensData(tokenRegContract, tokenIndexes) {
  return function (dispatch, getState) {var _getState4 =
    getState(),api = _getState4.api,tokens = _getState4.tokens;
    var allTokens = Object.values(tokens);

    var tokensIndexesMap = allTokens.
    reduce(function (map, token) {
      map[token.index] = token;
      return map;
    }, {});

    var fetchedTokenIndexes = allTokens.
    filter(function (token) {return token.fetched;}).
    map(function (token) {return token.index;});

    var fullIndexes = [];
    var partialIndexes = [];

    tokenIndexes.forEach(function (tokenIndex) {
      if (fetchedTokenIndexes.includes(tokenIndex)) {
        partialIndexes.push(tokenIndex);
      } else {
        fullIndexes.push(tokenIndex);
      }
    });

    log.debug('need to fully fetch', fullIndexes);
    log.debug('need to partially fetch', partialIndexes);

    var fullPromise = (0, _tokens.fetchTokensInfo)(api, tokenRegContract, fullIndexes);
    var partialPromise = (0, _tokens.fetchTokensImages)(api, tokenRegContract, partialIndexes).
    then(function (imagesResult) {
      return imagesResult.map(function (image, index) {
        var tokenIndex = partialIndexes[index];
        var token = tokensIndexesMap[tokenIndex];

        return _extends({}, token, { image: image });
      });
    });

    return Promise.all([fullPromise, partialPromise]).
    then(function (_ref) {var _ref2 = _slicedToArray(_ref, 2),fullResults = _ref2[0],partialResults = _ref2[1];
      log.debug('fetched', { fullResults: fullResults, partialResults: partialResults });

      return [].
      concat(fullResults, partialResults).
      reduce(function (tokens, token) {var
        id = token.id;

        tokens[id] = token;
        return tokens;
      }, {});
    }).
    then(function (tokens) {
      dispatch(setTokens(tokens));
    });
  };
}