'use strict';

import dateFormat    from 'dateformat';
import log           from 'fancy-log';
import colors        from 'ansi-colors';
import plugins       from 'gulp-load-plugins';
import yargs         from 'yargs';
import browser       from 'browser-sync';
import gulp          from 'gulp';
import panini        from 'panini';
import rimraf        from 'rimraf';
import sherpa        from 'style-sherpa';
import yaml          from 'js-yaml';
import fs            from 'fs';
import webpackStream from 'webpack-stream';
import webpack2      from 'webpack';
import named         from 'vinyl-named';
import uncss         from 'uncss';
import autoprefixer  from 'autoprefixer';

// added to have fontawesome support
gulp.task('icons', function() {
    return gulp.src('node_modules/@fortawesome/fontawesome-free/webfonts/*')
        .pipe(gulp.dest(dist+'/assets/webfonts/'));
});
// end fontawesome


// Load all Gulp plugins into one variable
const $ = plugins();

// Check for --production flag
const PRODUCTION = !!(yargs.argv.production);

// Check for --development flag unminified with sourcemaps
const DEV = !!(yargs.argv.dev);

// Load settings from settings.yml
//const { BROWSERSYNC, COMPATIBILITY, REVISIONING, PATHS } = loadConfig();
//const { PORT, UNCSS_OPTIONS, PATHS } = loadConfig();
const { PORT, UNCSS_OPTIONS, PATHS, BROWSERSYNC, COMPATIBILITY, REVISIONING } = loadConfig();

// Check if file exists synchronously
function checkFileExists(filepath) {
  let flag = true;
  try {
    fs.accessSync(filepath, fs.F_OK);
  } catch(e) {
    flag = false;
  }
  return flag;
}

// Load default or custom YML config file
function loadConfig() {
  log('Loading config file...');

  if (checkFileExists('config.yml')) {
    // config.yml exists, load it
    log(colors.bold(colors.cyan('config.yml')), 'exists, loading', colors.bold(colors.cyan('config.yml')));
    let ymlFile = fs.readFileSync('config.yml', 'utf8');
    return yaml.load(ymlFile);

  } else if(checkFileExists('config-default.yml')) {
    // config-default.yml exists, load it
    log(colors.bold(colors.cyan('config.yml')), 'does not exist, loading', colors.bold(colors.cyan('config-default.yml')));
    let ymlFile = fs.readFileSync('config-default.yml', 'utf8');
    return yaml.load(ymlFile);

  } else {
    // Exit if config.yml & config-default.yml do not exist
    log('Exiting process, no config file exists.');
    log('Error Code:', err.code);
    process.exit(1);
  }
}


// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
  rimraf(PATHS.dist, done);
}

// Copy files out of the assets folder
// This task skips over the "images", "js", and "scss" folders, which are parsed separately
function copy() {
  return gulp.src(PATHS.assets)
    .pipe(gulp.dest(PATHS.dist + '/assets'));
}

// no need for panini/html files
//
// Copy page templates into finished HTML files
//function pages() {
//  return gulp.src('src/pages/**/*.{html,hbs,handlebars}')
//    .pipe(panini({
//      root: 'src/pages/',
//      layouts: 'src/layouts/',
//      partials: 'src/partials/',
//      data: 'src/data/',
//      helpers: 'src/helpers/'
//    }))
//    .pipe(gulp.dest(PATHS.dist));
//}
// Load updated HTML templates and partials into Panini
//function resetPages(done) {
//  panini.refresh();
//  done();
//}
//
// no need for styleguide
//
// Generate a style guide from the Markdown content and HTML template in styleguide/
//function styleGuide(done) {
//  sherpa('src/styleguide/index.md', {
//    output: PATHS.dist + '/styleguide.html',
//    template: 'src/styleguide/template.html'
//  }, done);
//}




// Compile Sass into CSS
// In production, the CSS is compressed
function sass() {

  const postCssPlugins = [
    // Autoprefixer
    autoprefixer(),

    // UnCSS - Uncomment to remove unused styles in production
    // PRODUCTION && uncss.postcssPlugin(UNCSS_OPTIONS),
  ].filter(Boolean);

  //return gulp.src('src/assets/scss/app.scss')
  //  if need editor for CMS backend uncoment below coment above
  //  we need editor.scss for the wordpress editor styles
  return gulp.src(['src/assets/scss/app.scss','src/assets/scss/editor.scss'])
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      includePaths: PATHS.sass
    })
      .on('error', $.sass.logError))
    .pipe($.postcss(postCssPlugins))
    .pipe($.if(PRODUCTION, $.cleanCss({ compatibility: 'ie9' })))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/css'))
    .pipe($.if(REVISIONING && PRODUCTION || REVISIONING && DEV, $.rev.manifest()))
    .pipe(gulp.dest(PATHS.dist + '/assets/css'))
    .pipe(browser.reload({ stream: true }));
}

let webpackConfig = {
  mode: (PRODUCTION ? 'production' : 'development'),
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [ "@babel/preset-env" ],
            compact: false
          }
        }
      }
    ]
  },
  devtool: !PRODUCTION && 'source-map'
}


// Combine JavaScript into one file
// In production, the file is minified
function javascript() {
  return gulp.src(PATHS.entries)
    .pipe(named())
    .pipe($.sourcemaps.init())
    .pipe(webpackStream(webpackConfig, webpack2))
    .pipe($.if(PRODUCTION, $.terser()
      .on('error', e => { console.log(e); })
    ))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(PATHS.dist + '/assets/js'));
}

// Copy images to the "dist" folder
// In production, the images are compressed
function compressimages() {
}
function images() {
  return gulp.src('src/assets/images/**/*')
    .pipe($.if(PRODUCTION, $.imagemin([
      //$.imagemin.jpegtran({
      //  progressive: true,
      //}),
      $.imagemin.optipng({
        optimizationLevel: 5,
      }),
			$.imagemin.gifsicle({
        interlaced: true,
      }),
			$.imagemin.svgo({
        plugins: [
          {cleanupAttrs: true},
          {removeComments: true},
        ]
      })
		])))
    .pipe(gulp.dest(PATHS.dist + '/assets/images'));
}
function img() {
  return gulp.src('src/assets/img/**/*')
    .pipe($.if(PRODUCTION, $.imagemin([
     // $.imagemin.jpegtran({
     //   progressive: true,
     // }),
      $.imagemin.optipng({
        optimizationLevel: 5,
      }),
			$.imagemin.gifsicle({
        interlaced: true,
      }),
			$.imagemin.svgo({
        plugins: [
          {cleanupAttrs: true},
          {removeComments: true},
        ]
      })
		])))
    .pipe(gulp.dest(PATHS.dist + '/assets/img'));
}

// Create a .zip archive of the theme
function archive() {
  var time = dateFormat(new Date(), "yyyy-mm-dd_HH-MM");
  var pkg = JSON.parse(fs.readFileSync('./package.json'));
  var title = pkg.name + '_' + time + '.zip';

  return gulp.src(PATHS.package)
    .pipe($.zip(title))
    .pipe(gulp.dest('packaged'));
}

// PHP Code Sniffer task
gulp.task('phpcs', function() {
  return gulp.src(PATHS.phpcs)
    .pipe($.phpcs({
      bin: 'wpcs/vendor/bin/phpcs',
      standard: './codesniffer.ruleset.xml',
      showSniffCode: true,
    }))
    .pipe($.phpcs.reporter('log'));
});

// PHP Code Beautifier task
gulp.task('phpcbf', function () {
  return gulp.src(PATHS.phpcs)
  .pipe($.phpcbf({
    bin: 'wpcs/vendor/bin/phpcbf',
    standard: './codesniffer.ruleset.xml',
    warningSeverity: 0
  }))
  .on('error', log)
  .pipe(gulp.dest('.'));
});

// NOT needed in Wordpress
// Start a server with BrowserSync to preview the site in
//function server(done) {
//  browser.init({
//    server: PATHS.dist, port: PORT
//  }, done);
//}


// NOT needed in Wordpress
// Reload the browser with BrowserSync
//function reload(done) {
//  browser.reload();
//  done();
//}

// Watch for changes to static assets, pages, Sass, and JavaScript
function watch() {
  gulp.watch(PATHS.assets, copy);
  gulp.watch('src/assets/scss/**/*.scss', sass)
    .on('change', path => log('File ' + colors.bold(colors.magenta(path)) + ' changed.'))
    .on('unlink', path => log('File ' + colors.bold(colors.magenta(path)) + ' was removed.'));
//  gulp.watch('src/assets/images/**/*').on('all', gulp.series(images, browser.reload));
//  gulp.watch('src/assets/img/**/*').on('all', gulp.series(img, browser.reload));
  gulp.watch('src/assets/{images,img}/**/*').on('all', gulp.series(images, browser.reload));
  gulp.watch('src/assets/js/**/*.js').on('all', gulp.series(javascript, browser.reload));
//  gulp.watch('**/*.php', reload)
//    .on('change', path => log('File ' + colors.bold(colors.magenta(path)) + ' changed.'))
//    .on('unlink', path => log('File ' + colors.bold(colors.magenta(path)) + ' was removed.'));
//  gulp.watch('src/assets/scss/**/*.scss').on('all', sass);
//  gulp.watch('src/pages/**/*.html').on('all', gulp.series(pages, browser.reload));
//  gulp.watch('src/{layouts,partials}/**/*.html').on('all', gulp.series(resetPages, pages, browser.reload));
//  gulp.watch('src/data/**/*.{js,json,yml}').on('all', gulp.series(resetPages, pages, browser.reload));
//  gulp.watch('src/helpers/**/*.js').on('all', gulp.series(resetPages, pages, browser.reload));
//  gulp.watch('src/styleguide/**').on('all', gulp.series(styleGuide, browser.reload));
}

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
  gulp.series(clean, gulp.parallel(javascript, images, img, copy), sass));
  //gulp.series(clean, gulp.parallel(javascript, images, copy), sass));

// Build the site, run the server, and watch for file changes
gulp.task('default',
  //gulp.series('build', server, watch));
  //no need of server, just watch
  gulp.series('build', watch));

// Package task
gulp.task('package',
  gulp.series('build', archive));

