'use strict';

const Controller = require('egg').Controller;
const moment = require('moment');
const { sep, extname } = require('path');
const fs = require('fs');
const awaitWriteStream = require('await-stream-ready').write;
const sendToWormhole = require('stream-wormhole');
const assert = require('assert');
const wxstream = require('stream');
const ffmpeg = require('fluent-ffmpeg');
const { BusinessError, ErrorCode } = require('naf-core').Error;

class FilesController extends Controller {

  async upload() {
    const { ctx, app } = this;
    const { appid, catalog, item } = ctx.params;
    assert(appid);
    const stream = await ctx.getFileStream();
    ctx.logger.debug(stream);

    const rootPath = `${app.config.cdn.repos_root_path}`;
    const rootUrl = `${app.config.cdn.repos_root_url}`;
    const dirs = [ appid ];
    if (catalog && catalog !== '_') {
      const subs = catalog.split('_');
      dirs.push(...subs);
    }
    const saved = await this.saveFile(rootPath, dirs, stream, item);
    const uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
    ctx.body = { errcode: 0, errmsg: 'ok', id: saved.id, name: saved.fileName, uri };
  }

  async saveFile(rootPath, dirs, stream, name) {
    const ctx = this.ctx;
    const ext = extname(stream.filename).toLowerCase();
    // TODO: 指定文件名或者按时间生成文件名
    // const name = moment().format('YYYYMMDDHHmmss');
    if (!name) name = moment().format('YYYYMMDDHHmmss');

    // TODO: 检查根路径是否存在,不存在则创建
    ctx.logger.debug('rootPath: ', rootPath);
    if (!fs.existsSync(rootPath)) {
      ctx.logger.debug('create dir: ', rootPath);
      fs.mkdirSync(rootPath);
    }
    // TODO: 检查分级目录是否存在,不存在则创建
    for (let i = 0; i < dirs.length; i++) {
      const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
      if (!fs.existsSync(p)) {
        fs.mkdirSync(p);
      }
    }

    const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
    const fileName = `${name}${ext}`;
    const writeStream = fs.createWriteStream(filePath + fileName);
    try {
      await awaitWriteStream(stream.pipe(writeStream));
    } catch (err) {
      await sendToWormhole(stream);
      throw err;
    }

    return { filePath, fileName, id: name };
  }

  async wxupload() {
    const { serverid, type, appid } = this.ctx.request.body;
    assert(serverid, 'serverid不允许为空');
    assert(type, 'type不允许为空');
    const { ctx, app } = this;
    const url = app.config.wx.wxdown(appid, serverid);
    const file = await this.ctx.curl(url);
    console.log(url);
    const stream = new wxstream.PassThrough();
    stream.end(file.data);
    const rootPath = `${app.config.cdn.repos_root_path}`;
    const rootUrl = `${app.config.cdn.repos_root_url}`;
    let uri;
    // 判断类型 0、图片 1、音频 2、视频
    if (type === '0') {
      const dirs = [ 'wximage' ];
      const saved = await this.wxsaveFile(rootPath, dirs, stream, '.jpg');
      uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
    } else if (type === '1') {
      const dirs = [ 'wxadio' ];
      const saved = await this.wxsaveFile(rootPath, dirs, stream, '.amr');
      // 音频时如果需要使用转码,以下调用ffmpeg进行转码处理
      // const hz = '.mp3';
      const resultname = `${saved.id}.amr`;
      // const ffurl = `${saved.filePath}${resultname}`;
      // if (!ffmpeg) throw new BusinessError(ErrorCode.SERVICE_FAULT, '转换失败');
      // new ffmpeg({ source: `${saved.filePath}${saved.fileName}` })
      //   .saveToFile(ffurl, function(retcode, error) {
      //   })
      //   .on('end', function() {
      //     // 在这里处理完成后的结果
      //     console.log('Finished processing');
      //   });
      uri = `${rootUrl}/${dirs.join('/')}/${resultname}`;
    } else if (type === '2') {
      const dirs = [ 'wxvideo' ];
      const saved = await this.wxsaveFile(rootPath, dirs, stream, '');
      uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
    }
    ctx.body = { errcode: 0, errmsg: 'ok', uri };
  }

  async wxsaveFile(rootPath, dirs, stream, ext) {
    const ctx = this.ctx;
    // TODO: 指定文件名或者按时间生成文件名
    const name = moment().format('YYYYMMDDHHmmss');

    // TODO: 检查根路径是否存在,不存在则创建
    ctx.logger.debug('rootPath: ', rootPath);
    if (!fs.existsSync(rootPath)) {
      ctx.logger.debug('create dir: ', rootPath);
      fs.mkdirSync(rootPath);
    }
    // TODO: 检查分级目录是否存在,不存在则创建
    for (let i = 0; i < dirs.length; i++) {
      const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
      if (!fs.existsSync(p)) {
        fs.mkdirSync(p);
      }
    }

    const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
    const fileName = `${name}${ext}`;
    console.log(filePath + fileName);
    const writeStream = fs.createWriteStream(filePath + fileName);
    try {
      await awaitWriteStream(stream.pipe(writeStream));
    } catch (err) {
      await sendToWormhole(stream);
      throw err;
    }

    return { filePath, fileName, id: name };
  }

}

module.exports = FilesController;