// article.js
// Copyright (C) 2022 DTP Technologies, LLC
// License: Apache-2.0

'use strict';

const util = require('util');
const execFile = util.promisify(require('child_process').execFile);

const { SiteService } = require('../../lib/site-lib');

class MediaService extends SiteService {

  constructor (dtp) {
    super(dtp, module.exports);
  }

  async ffmpeg (ffmpegArgs) {
    try {
      await execFile(process.env.DTP_FFMPEG_PATH, ffmpegArgs, {
        cwd: this.dtp.config.root,
        encoding: 'utf8',
      });
    } catch (error) {
      this.log.error('failed to execute ffprobe', { ffmpegArgs, error });
      throw error;
    }
  }

  async ffprobe (input, options) {
    options = Object.assign({
      streams: true,
      format: true,
      error: true,
    }, options);
    const ffprobeOpts = ['-print_format', 'json'];
    if (options.streams) {
      ffprobeOpts.push('-show_streams');
    }
    if (options.format) {
      ffprobeOpts.push('-show_format');
    }
    if (options.error) {
      ffprobeOpts.push('-show_error');
    }
    ffprobeOpts.push(input);

    try {
      const { stdout } = await execFile(process.env.DTP_FFPROBE_PATH, ffprobeOpts, {
        cwd: this.dtp.config.root,
        encoding: 'utf8',
      });
      const probe = JSON.parse(stdout);

      if (probe.format && probe.format.tags) {
        let keys = Object.keys(probe.format.tags);
        keys.forEach((key) => {
          probe.format.tags[key.replace(/\./g, '_')] = probe.format.tags[key];
          delete probe.format.tags[key];
        });
      }

      probe.duration = probe.format.duration;
      probe.width = probe.format.width;

      if (Array.isArray(probe.streams) && probe.streams.length) {
        const stream = probe.streams
          .find((stream) => stream.codec_type === 'video') || probe.streams[0];

        if (stream.duration) {
          probe.duration = parseFloat(stream.duration);
        } else {
          probe.duration = parseFloat(probe.format.duration);
        }
        probe.width = stream.width;
        probe.height = stream.height;

        const fpsFraction = stream.avg_frame_rate.split('/').map((value) => parseInt(value, 10));
        if (Array.isArray(fpsFraction) && fpsFraction[1] !== 0) {
          probe.fps = fpsFraction[0] / fpsFraction[1];
        }
      } else {
        probe.duration = undefined;
        probe.width = undefined;
        probe.height = undefined;
      }

      return probe;
    } catch (error) {
      this.log.error('failed to execute ffprobe', { input, error });
      throw error;
    }
  }
}

module.exports = {
  slug: 'media',
  name: 'media',
  create: (dtp) => { return new MediaService(dtp); },
};