const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const mime = require('mime-types');

/**
 * Uploads (recursively) the contens of localDir to an S3 bucket with a prefix, using provided S3 client.
 * @param {S3} s3 S3 client form aws-sdk library
 * @param {string} localDir Local directory to upload
 * @param {string} bucket S3 bucket
 * @param {string} prefix Path on the S3 bucket
 */
async function uploadDir(s3, localDir, bucket, prefix) {
  const promises = [];

  fs.readdir(localDir, async (err, files) => {
    if(!files || files.length === 0) {
      console.log(`provided folder '${localDir}' is empty or does not exist.`);
      console.log('Make sure your project was compiled!');
      return;
    }

    // for each file in the directory
    for (const fileName of files) {

      // get the full path of the file
      const filePath = path.join(localDir, fileName);

      // decide what a remote path to the file should look like
      const remotePath = `${ prefix ? `${prefix}/${fileName}` : `${fileName}`}`;

      // ignore if directory
      if (fs.lstatSync(filePath).isDirectory()) {
        await uploadDir(s3, filePath, bucket, remotePath);
        continue;
      }

      // read file contents
      fs.readFile(filePath, (error, fileContent) => {
        // if unable to read file contents, throw exception
        if (error) { throw error; }

        // get content-type, fallback to binary
        const mimetype = mime.lookup(filePath) || 'application/octet-stream';
        const uploadPromise = new Promise((resolve, reject) => {
          // upload file to S3
          s3.upload({
            Bucket: bucket,
            Key: remotePath,
            Body: fileContent,
            ContentType: mimetype
          }, (res) => {
            console.log(`Pushed ${chalk.default.yellow(filePath)} to ${chalk.default.yellow(fileName)}`);
            resolve();
          });
        });
        promises.push(uploadPromise);
      });
    }
  });
  return Promise.all(promises);
}

module.exports = uploadDir;
