import memoize from 'lodash.memoize';
import IntlMessageFormat from 'intl-messageformat';

/* eslint-disable no-console */

function isEmpty(data) {
  return !data || Object.keys(data).length === 0;
}

const emptyLocaleDataWarned = {};
const notFoundKeyWarned = {};

function getLangString(locale, data, fullpath) {
  if (fullpath.filter(key => typeof key !== 'string').length > 0) {
    console.error('Invalid langpack path: ', fullpath);
  }

  const str = fullpath.reduce(
    (obj, key, idx) => {
      if (idx === fullpath.length - 1) {
        if (obj && (obj[key] !== undefined)) {
          return obj[key].toString();
        } else {
          const keyPath = `${locale}:${fullpath.join('/')}`;
          if (!isEmpty(data) && !notFoundKeyWarned[keyPath]) {
            console.warn(`Redux-Pagan: key was not found at path: ${keyPath}`);
            notFoundKeyWarned[keyPath] = true;
          }
          return key;
        }
      } else {
        return (obj && obj[key]) ? obj[key] : null
      }
    },
    data
  );

  if (str && !(typeof str === 'string')) {
    console.warn('String expected, got: ', str);
  }

  return str;
}

function concatPath(locale, data, path, subpath) {
  if (isEmpty(data) && !emptyLocaleDataWarned[locale]) {
    console.warn(`Redux-Pagan: got empty data for locale '${locale}'`);
    emptyLocaleDataWarned[locale] = true;
  }

  if (subpath.length === 0) {
    return getLangString(locale, data, path);
  }
  const _path = [...path, ...subpath];

  const i18nPartial = function(..._subpath) {
    return concatPath(locale, data, _path, _subpath);
  };

  const memoizedI18nPartial = memoize(i18nPartial, function(..._subpath) {
    return [locale, ..._path, ..._subpath].join(',');
  });

  memoizedI18nPartial.toString = function() {
    return getLangString(locale, data, _path);
  }

  memoizedI18nPartial.format = function(values) {
    const str = getLangString(locale, data, _path);
    const formatter = new IntlMessageFormat(str, locale);
    return formatter.format(values);
  }

  Object.defineProperty(memoizedI18nPartial, 's', {
    get() { return this.toString(); }
  });

  // proxy string methods
  Object.getOwnPropertyNames(String.prototype).forEach(prop => {
    if (typeof String.prototype[prop] === 'function' &&
      ['constructor', 'toString', 'valueOf'].indexOf(prop) === -1) { // find more elegant way maybe
      Object.defineProperty(memoizedI18nPartial, prop, {
        get() { return this.toString()[prop]; }
      });
    }
  });

  memoizedI18nPartial[Symbol.iterator] = function *() {
    yield memoizedI18nPartial.toString();
  }

  return memoizedI18nPartial;
}

/* eslint-enable no-console */

export default memoize(function i18nResolver(locale, data, version, ...path) {
  return concatPath(locale, data, [], path);
}, function(locale, data, version, ...path) {
  return [locale, version, ...path].join(',');
});

@@ -373,24 +373,75 @@
 ngth %3E 0) %7B%0A
+    if (process.env.NODE_ENV !== 'production') %7B%0A  
     console.
@@ -480,24 +480,30 @@
  fullpath);%0A
+    %7D%0A
   %7D%0A%0A  const
@@ -814,24 +814,83 @@
 keyPath%5D) %7B%0A
+            if (process.env.NODE_ENV !== 'production') %7B%0A  
             
@@ -953,24 +953,38 @@
 keyPath%7D%60);%0A
+            %7D%0A
             
@@ -1197,24 +1197,75 @@
 string')) %7B%0A
+    if (process.env.NODE_ENV !== 'production') %7B%0A  
     console.
@@ -1301,16 +1301,22 @@
 , str);%0A
+    %7D%0A
   %7D%0A%0A  r
@@ -1433,24 +1433,75 @@
 %5Blocale%5D) %7B%0A
+    if (process.env.NODE_ENV !== 'production') %7B%0A  
     console.
@@ -1556,24 +1556,30 @@
 locale%7D'%60);%0A
+    %7D%0A
     emptyLoc

remove console output in production