const debug = require("debug")("streamroller:RollingFileWriteStream");
const _ = require("lodash");
const async = require("async");
const fs = require("fs-extra");
const zlib = require("zlib");
const path = require("path");
const newNow = require("./now");
const format = require("date-format");
const { Writable } = require("stream");

const FILENAME_SEP = ".";
const ZIP_EXT = ".gz";

const moveAndMaybeCompressFile = (
  sourceFilePath,
  targetFilePath,
  needCompress,
  done
) => {
  if (sourceFilePath === targetFilePath) {
    debug(
      `moveAndMaybeCompressFile: source and target are the same, not doing anything`
    );
    return done();
  }
  fs.access(sourceFilePath, fs.constants.W_OK | fs.constants.R_OK, e => {
    if (e) {
      debug(
        `moveAndMaybeCompressFile: source file path does not exist. not moving. sourceFilePath=${sourceFilePath}`
      );
      return done();
    }

    debug(
      `moveAndMaybeCompressFile: moving file from ${sourceFilePath} to ${targetFilePath} ${
        needCompress ? "with" : "without"
      } compress`
    );
    if (needCompress) {
      fs.createReadStream(sourceFilePath)
        .pipe(zlib.createGzip())
        .pipe(fs.createWriteStream(targetFilePath))
        .on("finish", () => {
          debug(
            `moveAndMaybeCompressFile: finished compressing ${targetFilePath}, deleting ${sourceFilePath}`
          );
          fs.unlink(sourceFilePath, done);
        });
    } else {
      debug(
        `moveAndMaybeCompressFile: deleting file=${targetFilePath}, renaming ${sourceFilePath} to ${targetFilePath}`
      );
      fs.unlink(targetFilePath, () => {
        fs.rename(sourceFilePath, targetFilePath, done);
      });
    }
  });
};

/**
 * RollingFileWriteStream is mainly used when writing to a file rolling by date or size.
 * RollingFileWriteStream inhebites from stream.Writable
 */
class RollingFileWriteStream extends Writable {
  /**
   * Create a RollingFileWriteStream
   * @constructor
   * @param {string} filePath - The file path to write.
   * @param {object} options - The extra options
   * @param {number} options.numToKeep - The max numbers of files to keep.
   * @param {number} options.maxSize - The maxSize one file can reach. Unit is Byte.
   *                                   This should be more than 1024. The default is Number.MAX_SAFE_INTEGER.
   * @param {string} options.mode - The mode of the files. The default is '0644'. Refer to stream.writable for more.
   * @param {string} options.flags - The default is 'a'. Refer to stream.flags for more.
   * @param {boolean} options.compress - Whether to compress backup files.
   * @param {boolean} options.keepFileExt - Whether to keep the file extension.
   * @param {string} options.pattern - The date string pattern in the file name.
   * @param {boolean} options.alwaysIncludePattern - Whether to add date to the name of the first file.
   */
  constructor(filePath, options) {
    debug(`creating RollingFileWriteStream. path=${filePath}`);
    super(options);
    this.options = this._parseOption(options);
    this.fileObject = path.parse(filePath);
    if (this.fileObject.dir === "") {
      this.fileObject = path.parse(path.join(process.cwd(), filePath));
    }
    this.justTheFile = this._formatFileName({ isHotFile: true });
    this.filename = path.join(this.fileObject.dir, this.justTheFile);
    this.state = {
      currentSize: 0
    };

    if (this.options.pattern) {
      this.state.currentDate = format(this.options.pattern, newNow());
    }

    if (this.options.flags === "a") {
      this._setExistingSizeAndDate();
    }

    debug(
      `create new file with no hot file. name=${
        this.justTheFile
      }, state=${JSON.stringify(this.state)}`
    );
    this._renewWriteStream();
  }

  _setExistingSizeAndDate() {
    try {
      const stats = fs.statSync(this.filename);
      this.state.currentSize = stats.size;
      if (this.options.pattern) {
        this.state.currentDate = format(this.options.pattern, stats.birthtime);
      }
    } catch (e) {
      //file does not exist, that's fine - move along
      return;
    }
  }

  _parseOption(rawOptions) {
    const defaultOptions = {
      maxSize: Number.MAX_SAFE_INTEGER,
      numToKeep: Number.MAX_SAFE_INTEGER,
      encoding: "utf8",
      mode: parseInt("0644", 8),
      flags: "a",
      compress: false,
      keepFileExt: false,
      alwaysIncludePattern: false
    };
    const options = _.defaults({}, rawOptions, defaultOptions);
    if (options.maxSize <= 0) {
      throw new Error(`options.maxSize (${options.maxSize}) should be > 0`);
    }
    if (options.numToKeep <= 0) {
      throw new Error(`options.numToKeep (${options.numToKeep}) should be > 0`);
    }
    debug(`creating stream with option=${JSON.stringify(options)}`);
    return options;
  }

  _shouldRoll(callback) {
    if (
      this.state.currentDate &&
      this.state.currentDate !== format(this.options.pattern, newNow())
    ) {
      debug(
        `_shouldRoll: rolling by date because ${
          this.state.currentDate
        } !== ${format(this.options.pattern, newNow())}`
      );
      this._roll({ isNextPeriod: true }, callback);
      return;
    }
    if (this.state.currentSize >= this.options.maxSize) {
      debug(
        `_shouldRoll: rolling by size because ${this.state.currentSize} >= ${this.options.maxSize}`
      );
      this._roll({ isNextPeriod: false }, callback);
      return;
    }
    callback();
  }

  _write(chunk, encoding, callback) {
    this._shouldRoll(() => {
      debug(
        `writing chunk. ` +
          `file=${this.currentFileStream.path} ` +
          `state=${JSON.stringify(this.state)} ` +
          `chunk=${chunk}`
      );
      this.currentFileStream.write(chunk, encoding, e => {
        this.state.currentSize += chunk.length;
        callback(e);
      });
    });
  }

  // Sorted from the oldest to the latest
  _getExistingFiles(cb) {
    fs.readdir(this.fileObject.dir, (e, files) => {
      debug(`_getExistingFiles: files=${files}`);
      const existingFileDetails = _.compact(
        _.map(files, n => {
          const parseResult = this._parseFileName(n);
          debug(`_getExistingFiles: parsed ${n} as `, parseResult);
          if (!parseResult) {
            return;
          }
          return _.assign({ fileName: n }, parseResult);
        })
      );
      cb(
        null,
        _.sortBy(
          existingFileDetails,
          n =>
            (n.date
              ? format.parse(this.options.pattern, n.date).valueOf()
              : newNow().valueOf()) - n.index
        )
      );
    });
  }

  // need file name instead of file abs path.
  _parseFileName(fileName) {
    let isCompressed = false;
    if (fileName.endsWith(ZIP_EXT)) {
      fileName = fileName.slice(0, -1 * ZIP_EXT.length);
      isCompressed = true;
    }
    let metaStr;
    if (this.options.keepFileExt) {
      const prefix = this.fileObject.name + FILENAME_SEP;
      const suffix = this.fileObject.ext;
      if (!fileName.startsWith(prefix) || !fileName.endsWith(suffix)) {
        return;
      }
      metaStr = fileName.slice(prefix.length, -1 * suffix.length);
      debug(
        `metaStr=${metaStr}, fileName=${fileName}, prefix=${prefix}, suffix=${suffix}`
      );
    } else {
      const prefix = this.fileObject.base;
      if (!fileName.startsWith(prefix)) {
        return;
      }
      metaStr = fileName.slice(prefix.length + 1);
      debug(`metaStr=${metaStr}, fileName=${fileName}, prefix=${prefix}`);
    }
    if (!metaStr) {
      return {
        index: 0,
        isCompressed
      };
    }
    if (this.options.pattern) {
      const items = _.split(metaStr, FILENAME_SEP);
      const indexStr = items[items.length - 1];
      debug("items: ", items, ", indexStr: ", indexStr);
      if (indexStr !== undefined && indexStr.match(/^\d+$/)) {
        const dateStr = metaStr.slice(0, -1 * (indexStr.length + 1));
        debug(`dateStr is ${dateStr}`);
        if (dateStr) {
          return {
            index: parseInt(indexStr, 10),
            date: dateStr,
            isCompressed
          };
        }
      }
      debug(`metaStr is ${metaStr}`);
      return {
        index: 0,
        date: metaStr,
        isCompressed
      };
    } else {
      if (metaStr.match(/^\d+$/)) {
        return {
          index: parseInt(metaStr, 10),
          isCompressed
        };
      }
    }
    return;
  }

  _formatFileName({ date, index, isHotFile }) {
    debug(
      `_formatFileName: date=${date}, index=${index}, isHotFile=${isHotFile}`
    );
    const dateStr =
      date ||
      _.get(this, "state.currentDate") ||
      format(this.options.pattern, newNow());
    const indexOpt = index || _.get(this, "state.currentIndex");
    const oriFileName = this.fileObject.base;
    if (isHotFile) {
      debug(
        `_formatFileName: includePattern? ${this.options.alwaysIncludePattern}, pattern: ${this.options.pattern}`
      );
      if (this.options.alwaysIncludePattern && this.options.pattern) {
        debug(
          `_formatFileName: is hot file, and include pattern, so: ${oriFileName +
            FILENAME_SEP +
            dateStr}`
        );
        return this.options.keepFileExt
          ? this.fileObject.name + FILENAME_SEP + dateStr + this.fileObject.ext
          : oriFileName + FILENAME_SEP + dateStr;
      }
      debug(`_formatFileName: is hot file so, filename: ${oriFileName}`);
      return oriFileName;
    }
    let fileNameExtraItems = [];
    if (this.options.pattern) {
      fileNameExtraItems.push(dateStr);
    }
    if (indexOpt && this.options.maxSize < Number.MAX_SAFE_INTEGER) {
      fileNameExtraItems.push(indexOpt);
    }
    let fileName;
    if (this.options.keepFileExt) {
      const baseFileName =
        this.fileObject.name +
        FILENAME_SEP +
        fileNameExtraItems.join(FILENAME_SEP);
      fileName = baseFileName + this.fileObject.ext;
    } else {
      fileName =
        oriFileName + FILENAME_SEP + fileNameExtraItems.join(FILENAME_SEP);
    }
    if (this.options.compress) {
      fileName += ZIP_EXT;
    }
    debug(`_formatFileName: ${fileName}`);
    return fileName;
  }

  _moveOldFiles(isNextPeriod, cb) {
    const currentFilePath = this.currentFileStream.path;
    debug(`numToKeep = ${this.options.numToKeep}`);
    const finishedRolling = () => {
      if (isNextPeriod) {
        this.state.currentSize = 0;
        this.state.currentDate = format(this.options.pattern, newNow());
        debug(`rolling for next period. state=${JSON.stringify(this.state)}`);
      } else {
        this.state.currentSize = 0;
        debug(
          `rolling during the same period. state=${JSON.stringify(this.state)}`
        );
      }
      this._renewWriteStream();
      // wait for the file to be open before cleaning up old ones,
      // otherwise the daysToKeep calculations can be off
      this.currentFileStream.write("", "utf8", () => this._clean(cb));
    };

    this._getExistingFiles((e, files) => {
      const filesToMove = [];
      const todaysFiles = this.state.currentDate
        ? files.filter(f => f.date === this.state.currentDate)
        : files;
      for (let i = todaysFiles.length; i >= 0; i--) {
        debug(`i = ${i}`);
        const sourceFilePath =
          i === 0
            ? currentFilePath
            : path.format({
                dir: this.fileObject.dir,
                base: this._formatFileName({
                  date: this.state.currentDate,
                  index: i
                })
              });
        const targetFilePath = path.format({
          dir: this.fileObject.dir,
          base: this._formatFileName({
            date: this.state.currentDate,
            index: i + 1
          })
        });
        filesToMove.push({ sourceFilePath, targetFilePath });
      }
      debug(`filesToMove = `, filesToMove);
      async.eachOfSeries(
        filesToMove,
        (files, idx, cb1) => {
          debug(
            `src=${files.sourceFilePath}, tgt=${
              files.sourceFilePath
            }, idx=${idx}, pos=${filesToMove.length - 1 - idx}`
          );
          moveAndMaybeCompressFile(
            files.sourceFilePath,
            files.targetFilePath,
            this.options.compress && filesToMove.length - 1 - idx === 0,
            cb1
          );
        },
        finishedRolling
      );
    });
  }

  _roll({ isNextPeriod }, cb) {
    debug(`rolling, isNextPeriod ? ${isNextPeriod}`);
    debug(`_roll: closing the current stream`);
    this.currentFileStream.end("", this.options.encoding, () => {
      this._moveOldFiles(isNextPeriod, cb);
    });
  }

  _renewWriteStream() {
    fs.ensureDirSync(this.fileObject.dir);
    this.justTheFile = this._formatFileName({
      date: this.state.currentDate,
      index: 0,
      isHotFile: true
    });
    const filePath = path.format({
      dir: this.fileObject.dir,
      base: this.justTheFile
    });
    const ops = _.pick(this.options, ["flags", "encoding", "mode"]);
    this.currentFileStream = fs.createWriteStream(filePath, ops);
    this.currentFileStream.on("error", e => {
      this.emit("error", e);
    });
  }

  _clean(cb) {
    this._getExistingFiles((e, existingFileDetails) => {
      debug(
        `numToKeep = ${this.options.numToKeep}, existingFiles = ${existingFileDetails.length}`
      );
      debug("existing files are: ", existingFileDetails);
      if (
        this.options.numToKeep > 0 &&
        existingFileDetails.length > this.options.numToKeep
      ) {
        const fileNamesToRemove = _.slice(
          existingFileDetails.map(f => f.fileName),
          0,
          existingFileDetails.length - this.options.numToKeep - 1
        );
        this._deleteFiles(fileNamesToRemove, cb);
        return;
      }
      cb();
    });
  }

  _deleteFiles(fileNames, done) {
    debug(`files to delete: ${fileNames}`);
    async.each(
      _.map(fileNames, f => path.format({ dir: this.fileObject.dir, base: f })),
      fs.unlink,
      done
    );
    return;
  }
}

module.exports = RollingFileWriteStream;
