// @ts-check

/**
 * Create htaccess file if not existing on user's machine
 *
 * @param {"" | "example" | "dev" | "staging" | "production"} name
 */
function maybeCreateFile(name, callback) {
  const filename = name ? `.htaccess.${name}` : ".htaccess";
  const { taskIfDevAndMissingFile } = require("../utils");
  const paths = require("../paths");

  return taskIfDevAndMissingFile(
    paths.join(paths.frontend.dest.public, filename),
    callback,
    () => {
      const gulp = require("gulp");

      return gulp
        .src(paths.join(paths.self.templates, filename), { dot: true })
        .pipe(gulp.dest(paths.frontend.dest.public));
    }
  );
}

/**
 * Create current .htaccess file
 */
function htaccessCurrent(callback) {
  return maybeCreateFile("", callback);
}

/**
 * Create htaccess "dev"
 */
function htaccessDev(callback) {
  return maybeCreateFile("dev", callback);
}

/**
 * Create htaccess "staging"
 */
function htaccessStaging(callback) {
  return maybeCreateFile("staging", callback);
}

/**
 * Create htaccess "production"
 */
function htaccessProduction(callback) {
  return maybeCreateFile("production", callback);
}

/**
 * Htaccess reusable function for hashed assets
 *
 * @param {string} dest
 * @param {string[]} extensions
 * @param {number} hours
 * @returns
 */
function _htaccessHashed(dest, extensions, hours) {
  const gulp = require("gulp");
  const rename = require("gulp-rename");
  const template = require("gulp-template");
  const paths = require("../paths");

  return gulp
    .src(paths.join(paths.self.templates, "htaccess-assets-hashed"))
    .pipe(
      // @ts-ignore
      template({
        extensions: extensions.join("|"),
        days: hours * 60 * 60,
      })
    )
    .pipe(rename(".htaccess"))
    .pipe(gulp.dest(dest));
}

function htaccessEntries() {
  const paths = require("../paths");
  return _htaccessHashed(
    paths.frontend.dest.entries,
    ["js", "css", "txt"],
    24 * 365
  );
}

function htaccessChunks() {
  const paths = require("../paths");
  return _htaccessHashed(
    paths.frontend.dest.chunks,
    ["js", "css", "txt"],
    24 * 365
  );
}

function htaccessImages() {
  const paths = require("../paths");
  return _htaccessHashed(
    paths.frontend.dest.images,
    ["gif", "png", "jpg", "jpeg", "svg", "webp"],
    24 * 365
  );
}

function htaccessFonts() {
  const paths = require("../paths");
  return _htaccessHashed(
    paths.frontend.dest.fonts,
    ["woff", "woff2", "ttf", "otf", "eot"],
    24 * 365
  );
}

function htaccessFavicons() {
  const paths = require("../paths");
  return _htaccessHashed(
    paths.frontend.dest.favicons,
    ["png", "json", "xml", "webapp", "ico"],
    4
  );
}

/**
 * Collect subtasks in a single task that respect the gulp async lifecycle by
 * calling the callback on completion.
 */
module.exports = function htaccess(callback) {
  const gulp = require("gulp");
  const { isProduction } = require("../config");

  return isProduction
    ? gulp.parallel(
        htaccessEntries,
        htaccessChunks,
        htaccessImages,
        htaccessFonts,
        htaccessFavicons
      )(callback)
    : gulp.parallel(
        htaccessCurrent,
        htaccessDev,
        htaccessStaging,
        htaccessProduction
      )(callback);
};
