const gulp = require("gulp"),
  sass = require("gulp-sass"),
  debug = require("gulp-debug"),
  babel = require("gulp-babel"),
  concat = require("gulp-concat"),
  rename = require("gulp-rename"),
  uglify = require("gulp-uglify"),
  sourcemaps = require("gulp-sourcemaps"),
  autoprefixer = require("gulp-autoprefixer"),
  browserSync = require("browser-sync").create(),
  through = require("through2"),
  webpackStream = require("webpack-stream")

// paths
const sourcePath = {
  scss: [
    "src/styles/app.scss",
    "src/styles/components/*.scss",
    "src/styles/global/*.scss",
    "src/styles/vendors/**/*.scss"
  ],
  cssDest: "dist/css",
  js: "src/scripts/**/*.js",
  jsDest: "dist/js",
  fonts: "src/styles/fonts/**",
  fontsDest: "dist/fonts",
  distImages: "Content/images/distribution/**",
  distImagesDest: "dist/css"
}

const fileName = {
  js: "app",
  css: "app"
}

// source files of the es6 and vendor files
const scripts = require("./scripts")

// compile SCSS
gulp.task("compileSass", () => {
  return gulp
    .src(sourcePath.scss)
    .pipe(sass({ sourceComments: "map" }).on("error", sass.logError))
    .pipe(autoprefixer())
    .pipe(rename(fileName.css + ".css"))
    .pipe(gulp.dest(sourcePath.cssDest))
    .pipe(browserSync.stream())
})

// minify css
gulp.task("minifyCss", () => {
  return gulp
    .src(sourcePath.scss)
    .pipe(sass({ outputStyle: "compressed" }))
    .pipe(rename(fileName.css + ".min.css"))
    .pipe(gulp.dest(sourcePath.cssDest))
})

// compile es6 javascript
gulp.task("compileEs6", () => {
  return gulp
    .src(scripts.es6Files)
    .pipe(
      babel({
        presets: ["@babel/preset-env"],
        plugins: [
          "@babel/plugin-transform-runtime",
          "@babel/plugin-transform-strict-mode"
        ]
      })
    )
    .pipe(concat(fileName.js + ".babelized.js"))
    .pipe(gulp.dest(sourcePath.jsDest))
    .pipe(browserSync.stream())
})

// stream 'babelized' through webpack to enables 'require'
gulp.task("webpackScripts", ["compileEs6"], function() {
  return gulp
    .src(sourcePath.jsDest + "/app.babelized.js")
    .pipe(
      debug({
        title: "Webpack: "
      })
    )
    .pipe(
      webpackStream({
        mode: "development",
        output: {
          filename: "app.webpacked.js"
        },
        devtool: "source-map"
      })
    )
    .pipe(sourcemaps.init({ loadMaps: true }))
    .pipe(
      through.obj(function(file, enc, cb) {
        // Dont pipe through any source map files as it will be handled
        // by gulp-sourcemaps
        const isSourceMap = /\.map$/.test(file.path)
        if (!isSourceMap) this.push(file)
        cb()
      })
    )
    .pipe(sourcemaps.write("."))
    .pipe(gulp.dest(sourcePath.jsDest))
})

// compile vendor js no need to babelized it
gulp.task("compileVendorJs", () => {
  return gulp
    .src(scripts.vendorFiles)
    .pipe(concat(fileName.js + ".vendor.js"))
    .pipe(gulp.dest(sourcePath.jsDest))
    .pipe(browserSync.stream())
})

// concatenate both vendor and babelized js
gulp.task("bundleScripts", ["webpackScripts", "compileVendorJs"], () => {
  return gulp
    .src([
      `${sourcePath.jsDest}/app.vendor.js`,
      `${sourcePath.jsDest}/app.webpacked.js`
    ])
    .pipe(concat(fileName.js + ".js"))
    .pipe(gulp.dest(sourcePath.jsDest))
    .pipe(browserSync.stream())
})

// copy the fonts and add it to dist folder
gulp.task("compileFonts", function() {
  return gulp.src([sourcePath.fonts]).pipe(gulp.dest(sourcePath.fontsDest))
})

// add the auto generated assets to dist
gulp.task("compileDistImages", function() {
  return gulp
    .src([sourcePath.distImages])
    .pipe(gulp.dest(sourcePath.distImagesDest))
})

// minify js
gulp.task("minifyJs", () => {
  return gulp
    .src(sourcePath.jsDest + "/" + fileName.js + ".js")
    .pipe(
      uglify().on("error", err => {
        console.log(err)
      })
    )
    .pipe(rename(fileName.js + ".min.js"))
    .pipe(gulp.dest(sourcePath.jsDest))
    .pipe(browserSync.stream())
})

// compile css and js for production
gulp.task("prod", ["minifyCss", "minifyJs"])

// watch changes for css and js
gulp.task(
  "watch",
  ["compileSass", "bundleScripts", "compileFonts", "compileDistImages"],
  () => {
    gulp.watch(sourcePath.scss, ["compileSass"])
    gulp.watch(sourcePath.js, ["bundleScripts"])
  }
)

// just run gulp to watch the css and js
gulp.task("default", ["watch"])
