"use strict";

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

var _cliProgress2 = _interopRequireDefault(require("cli-progress"));

var _fsExtra = _interopRequireDefault(require("fs-extra"));

var _ora = _interopRequireDefault(require("ora"));

var _path = _interopRequireDefault(require("path"));

var _progressStream = _interopRequireDefault(require("progress-stream"));

var _youtubeDl = _interopRequireDefault(require("youtube-dl"));

var _ = require(".");

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

/**
 * Download youtube video and save locally
 * @param {string} videoId Youtube video id to construct download url
 * @param {string} outputPath directory to save the file
 * @param {string} prefix file prefix
 * @param {string} title title of atom
 * @param {string} format youtube-dl quality setting (eg. best)
 */
function downloadYoutube(videoId, outputPath, prefix, title, format = 'best') {
  return new Promise((resolve, reject) => {
    if (!videoId) {
      resolve(null);
      return;
    }

    const filenameBase = `${prefix}. ${(0, _.filenamify)(title || '')}-${videoId}`;
    const filenameYoutube = `${filenameBase}.mp4`;
    const urlYoutube = `https://www.youtube.com/watch?v=${videoId}`;

    const savePath = _path.default.join(outputPath, filenameYoutube);

    `${outputPath}/${filenameYoutube}`;

    const tempPath = _path.default.join(outputPath, `.${filenameYoutube}`); // avoid re-downloading videos if it already exists


    if (_fsExtra.default.existsSync(savePath)) {
      _.logger.info(`Video already exists. Skip downloading ${savePath}`);

      const subtitles = (0, _.findVideoLocalSubtitles)(filenameBase, outputPath);
      resolve({
        src: filenameYoutube,
        subtitles
      });
      return;
    } // start youtube download


    const argsYoutube = [`--format=${format}`];
    global.ytVerbose && argsYoutube.push('--verbose');
    const spinnerInfo = (0, _ora.default)(`Getting Youtube video id ${videoId} information`).start();
    const video = (0, _youtubeDl.default)(urlYoutube, argsYoutube);
    video.on('info', info => {
      spinnerInfo.succeed(); // get video name

      const fileSize = info.size; // create a new progress bar instance

      const progressBar = new _cliProgress2.default.Bar({}, _cliProgress2.default.Presets.shades_classic);
      progressBar.start(fileSize, 0);
      const progressStream = (0, _progressStream.default)({
        length: fileSize,
        time: 20
      });
      progressStream.on('progress', progressData => {
        progressBar.update(progressData.transferred);
      }); // Write video to temporary file first. If download finishes, rename it
      // to proper file name later. This is to avoid the issue when the terminal
      // stop unexpectedly, when restart, the unfinished video will be
      // redownloaded

      video.pipe(progressStream).pipe(_fsExtra.default.createWriteStream(tempPath));
      video.on('end', async () => {
        // rename temp file to final file name
        try {
          await _fsExtra.default.rename(tempPath, savePath);
        } catch (errorRename) {
          reject(errorRename);
        }

        progressBar.update(fileSize);
        progressBar.stop();

        _.logger.info(`Downloaded video ${filenameYoutube}`);

        let subtitles;

        try {
          subtitles = await (0, _.downloadYoutubeSubtitles)(videoId, filenameBase, outputPath);
          resolve({
            src: filenameYoutube,
            subtitles
          });
        } catch (error) {
          _.logger.warn(error);

          resolve({
            src: filenameYoutube,
            subtitles: []
          });
        }
      }); //.video.on end
    }); //.video.on info

    video.on('error', error => {
      spinnerInfo.fail();
      const {
        message
      } = error;

      if (!message) {
        reject(error);
        return;
      } // handle video unavailable error. See node-youtube-dl source code for
      // error message strings to check


      if (message.includes('video is unavailable')) {
        _.logger.error(`Youtube video with id ${videoId} is unavailable. It may have been deleted. The CLI will ignore this error and skip this download.`);

        resolve(null);
      } else if (message.includes('video has been removed by the user')) {
        _.logger.error(`Youtube video with id ${videoId} has been removed by the user. The CLI will ignore this error and skip this download.`);

        resolve(null);
      } else if (message.includes('sign in to view this video')) {
        _.logger.error(`Youtube video with id ${videoId} is private and require user to sign in to access it. The CLI will ignore this error and skip this download.`);

        resolve(null);
      } else if (message.includes('video is no longer available')) {
        _.logger.error(`Youtube video with id ${videoId} is no longer available. The CLI will ignore this error and skip this download.`);

        resolve(null);
      } else {
        reject(error);
      }
    });
  }); //.return Promise
}