'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var consola = _interopDefault(require('consola'));
var child_process = require('child_process');
var chalk = _interopDefault(require('chalk'));
var path = _interopDefault(require('path'));
var fs = _interopDefault(require('fs'));
var fetch = _interopDefault(require('node-fetch'));

const reportAndThrowError = msg => {
  report(msg);
  throw new Error(msg);
};
const report = message => {
  consola.debug({
    message: String(message),
    tag: 'opencollective'
  });
};
const hideMessage = (env = process.env) => {
  // Show message if it is forced
  if (env.OPENCOLLECTIVE_FORCE) {
    return false;
  } // Don't show after oracle postinstall


  if (env.OC_POSTINSTALL_TEST) {
    return true;
  } // Don't show if opted-out


  if (env.OPENCOLLECTIVE_HIDE) {
    return true;
  } // Don't show if on CI


  if (env.CI || env.CONTINUOUS_INTEGRATION) {
    return true;
  } // Only show in dev environment


  return Boolean(env.NODE_ENV) && !['dev', 'development'].includes(env.NODE_ENV);
};
const formatMoney = currency => amount => {
  amount = amount / 100; // converting cents

  const precision = 0;
  return amount.toLocaleString(currency, {
    style: 'currency',
    currency: currency,
    minimumFractionDigits: precision,
    maximumFractionDigits: precision
  });
};
const isWin32 = process.platform === 'win32';
const stripLeadingSlash = s => s.startsWith('/') ? s.substring(1) : s;
const stripTrailingSlash = s => s.endsWith('/') ? s.slice(0, -1) : s;

/* eslint-disable no-console */
const print = (color = null) => (str = '') => {
  const terminalCols = retrieveCols();
  const strLength = str.replace(/\u001b\[[0-9]{2}m/g, '').length;
  const leftPaddingLength = Math.floor((terminalCols - strLength) / 2);
  const leftPadding = ' '.repeat(Math.max(leftPaddingLength, 0));

  if (color) {
    str = chalk[color](str);
  }

  console.log(leftPadding, str);
};
const retrieveCols = (() => {
  let result = false;
  return () => {
    if (result) {
      return result;
    }

    const defaultCols = 80;

    try {
      const terminalCols = child_process.execSync(`tput cols`, {
        stdio: ['pipe', 'pipe', 'ignore']
      });
      result = parseInt(terminalCols.toString()) || defaultCols;
    } catch (e) {
      result = defaultCols;
    }

    return result;
  };
})();
const printStats = (stats, color) => {
  if (!stats) {
    return;
  }

  const colored = print(color);
  const bold = print('bold');
  const formatWithCurrency = formatMoney(stats.currency);
  colored(`Number of contributors: ${stats.contributorsCount}`);
  colored(`Number of backers: ${stats.backersCount}`);
  colored(`Annual budget: ${formatWithCurrency(stats.yearlyIncome)}`);
  bold(`Current balance: ${formatWithCurrency(stats.balance)}`, 'bold');
};
const printLogo = logoText => {
  if (!logoText) {
    return;
  }

  logoText.split('\n').forEach(print('blue'));
};
/**
 * Only show emoji on OSx (Windows shell doesn't like them that much ¯\_(ツ)_/¯ )
 * @param {*} emoji
 */

const emoji = emoji => process.stdout.isTTY && !isWin32 ? emoji : '';
function printFooter(collective) {
  const dim = print('dim');
  const yellow = print('yellow');
  const emptyLine = print();
  yellow(`Thanks for installing ${collective.slug} ${emoji('🙏')}`);
  dim(`Please consider donating to our open collective`);
  dim(`to help us maintain this package.`);
  emptyLine();
  printStats(collective.stats);
  emptyLine();
  print()(`${chalk.bold(`${emoji('👉 ')} ${collective.donationText}`)} ${chalk.underline(collective.donationUrl)}`);
  emptyLine();
}

function _slicedToArray(arr, i) {
  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}

function _arrayWithHoles(arr) {
  if (Array.isArray(arr)) return arr;
}

function _iterableToArrayLimit(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"] != null) _i["return"]();
    } finally {
      if (_d) throw _e;
    }
  }

  return _arr;
}

function _nonIterableRest() {
  throw new TypeError("Invalid attempt to destructure non-iterable instance");
}

const FETCH_TIMEOUT = 3000;

const fetchJson = url => new Promise(function ($return, $error) {
  var $Try_1_Post = function () {
    try {
      return $return();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  var $Try_1_Catch = function (e) {
    try {
      report(e);
      reportAndThrowError(`Could not fetch ${url}.json`);
      return $Try_1_Post();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  try {
    return Promise.resolve(global.fetch(`${url}.json`, {
      timeout: FETCH_TIMEOUT
    })).then(function ($await_5) {
      try {
        return $return($await_5.json());
      } catch ($boundEx) {
        return $Try_1_Catch($boundEx);
      }
    }, $Try_1_Catch);
  } catch (e) {
    $Try_1_Catch(e);
  }
});

const fetchStats = collectiveUrl$$1 => new Promise(function ($return, $error) {
  var $Try_2_Post = function () {
    try {
      return $return();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  var $Try_2_Catch = function (e) {
    try {
      report(e);
      report(`Could not load the stats for ${collectiveSlugFromUrl(collectiveUrl$$1)}`);
      return $Try_2_Post();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  try {
    return Promise.resolve(fetchJson(collectiveUrl$$1)).then($return, $Try_2_Catch);
  } catch (e) {
    $Try_2_Catch(e);
  }
});
const fetchLogo = logoUrl => new Promise(function ($return, $error) {
  if (!logoUrl) {
    // Silent return if no logo has been provided
    return $return();
  }

  if (!logoUrl.match(/^https?:\/\//)) {
    reportAndThrowError(`Your logo URL isn't well-formatted - ${logoUrl}`);
  }

  var $Try_3_Post = function () {
    try {
      return $return();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  var $Try_3_Catch = function (e) {
    try {
      report(`Error while fetching logo from ${logoUrl}`);
      return $Try_3_Post();
    } catch ($boundEx) {
      return $error($boundEx);
    }
  };

  try {
    let res;
    return Promise.resolve(global.fetch(logoUrl, {
      timeout: FETCH_TIMEOUT
    })).then(function ($await_7) {
      try {
        res = $await_7;

        if (isLogoResponseWellFormatted(res)) {
          return $return(res.text());
        }

        report(`Error while fetching logo from ${logoUrl}. The response wasn't well-formatted`);
        return $Try_3_Post();
      } catch ($boundEx) {
        return $Try_3_Catch($boundEx);
      }
    }, $Try_3_Catch);
  } catch (e) {
    $Try_3_Catch(e);
  }
});

const isLogoResponseWellFormatted = res => res.status === 200 && res.headers.get('content-type').match(/^text\/plain/);

const fetchPkg = pathToPkg => {
  const fullPathToPkg = path.resolve(`${pathToPkg}/package.json`);

  try {
    return JSON.parse(fs.readFileSync(fullPathToPkg, 'utf8'));
  } catch (e) {
    reportAndThrowError(`Could not find package.json at ${fullPathToPkg}`);
  }
};

const collectiveSlugFromUrl = url => url.substr(url.lastIndexOf('/') + 1).toLowerCase().replace(/\.json/g, '');
const collectiveUrl = pkg => {
  const url = pkg.collective && pkg.collective.url;

  if (!url) {
    reportAndThrowError('No collective URL set!');
  }

  return stripTrailingSlash(url);
}; // use pkg.collective.logo for "legacy"/compatibility reasons

const collectiveLogoUrl = pkg => pkg.collective.logo || pkg.collective.logoUrl || false;
const collectiveDonationText = pkg => pkg.collective.donation && pkg.collective.donation.text || 'Donate:';
const getCollective = pkgPath => new Promise(function ($return, $error) {
  let pkg, url, baseCollective, logoUrl, promises, _ref, _ref2, stats, logo;

  pkg = fetchPkg(pkgPath);
  url = collectiveUrl(pkg);
  baseCollective = {
    url,
    slug: collectiveSlugFromUrl(url),
    logoUrl: collectiveLogoUrl(pkg),
    donationUrl: collectiveDonationUrl(pkg),
    donationText: collectiveDonationText(pkg)
  };
  logoUrl = baseCollective.logoUrl;
  promises = [fetchStats(url)].concat(logoUrl ? fetchLogo(logoUrl) : []);
  return Promise.resolve(Promise.all(promises)).then(function ($await_1) {
    try {
      _ref = $await_1, _ref2 = _slicedToArray(_ref, 2), stats = _ref2[0], logo = _ref2[1];
      return $return(Object.assign(baseCollective, {
        stats,
        logo
      }));
    } catch ($boundEx) {
      return $error($boundEx);
    }
  }, $error);
});
const collectiveDonationUrl = pkg => {
  const defaultDonationAmount = pkg.collective.donation && pkg.collective.donation.amount;
  let donateUrl = `${collectiveUrl(pkg)}/${retrieveDonationSlug(pkg)}`;

  if (defaultDonationAmount) {
    return `${donateUrl}/${defaultDonationAmount}`;
  }

  return donateUrl;
};
const retrieveDonationSlug = pkg => {
  const rawDonationSlug = pkg.collective.donation && pkg.collective.donation.slug;

  if (!rawDonationSlug) {
    return 'donate';
  }

  return stripLeadingSlash(rawDonationSlug);
};

function init(path$$1, hide = hideMessage()) {
  return new Promise(function ($return, $error) {
    let collective;

    if (hide) {
      return $return();
    }

    global.fetch = global.fetch || fetch;
    return Promise.resolve(getCollective(path$$1)).then(function ($await_1) {
      try {
        collective = $await_1;
        printLogo(collective.logo);
        printFooter(collective);
        return $return();
      } catch ($boundEx) {
        return $error($boundEx);
      }
    }, $error);
  });
}

exports.init = init;