const gulp = require('gulp');
const rev = require('gulp-rev');
const revFormat = require('gulp-rev-format');
const revCollector = require('gulp-rev-collector');
const htmlmin = require('gulp-htmlmin');
const uglify = require('gulp-uglify');
const cleanCSS = require('gulp-clean-css');
const autoprefixer = require('gulp-autoprefixer');
const gulpSequence = require('gulp-sequence');
const del = require('del');
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const fileinclude = require('gulp-file-include');
const browserSync = require('browser-sync').create();
const chalk = require('chalk');

// 终端输出颜色
const chalkColorRed = '#f04134';
const chalkColorGreen = '#00a854';
const chalkColorBlue = '#108ee9';
const chalkColorPink = '#f5317f';
const chalkColorOrange = '#f56a00';
const chalkColorPurple = '#7265e6';
const chalkColorYellow = '#ffbf00';
const chalkColorCyan = '#00a2ae';

// 端口号
const PORT = 7999;

// 基础目录
const Src = './src';
const Dist = './dist';
const Build = './build';

// 源文件相关
const srcIndexHtml = `${Src}/index.html`;
const srcPageIndexHtml = `${Src}/page/index.html`;
const srcJs = `${Src}/js/*.js`;
const srcDataJs = `${Src}/data/*.js`;
const srcI18nJs = `${Src}/i18n/*.js`;
const srcIndexSass = `${Src}/sass/index.scss`;
const srcSass = `${Src}/sass/*.scss`;
const srcStyle = `${Src}/theme/style.css`;
const srcTemplate = `${Src}/template/**/*.mustache`;

// 版本号相关
const revJs = 'rev-manifest-js.json';
const revCss = 'rev-manifest-css.json';
const buildJson = `${Build}/*.json`;

// 输出子串
const eqSpliter = `=================`;
const startSpliter = `| ${eqSpliter} [ @ START ] ${eqSpliter} |`;
const endSpliter = `| ${eqSpliter} [ @  END  ] ${eqSpliter} |`;

const arrowStr = `| ===>>>`;
const taskStr = `${arrowStr} task: `;
const watchStr = `${arrowStr} watch: `;

// -----------------------------------------------------------------------------
gulp.task('simpleCopy', ['clean'], function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 对一些文件做简单的拷贝 ...`));
    let folder = [
        `${Src}/libs/**`,
        `${Src}/assets/**`,
        `${Src}/theme/fonts/**`,
        `${Src}/theme/awesome-fonts/**`,
        `${Src}/theme/img/**`,
        `${Src}/theme/styles/**`
    ];
    return gulp.src(folder, {
            base: `${Src}`
        })
        .pipe(gulp.dest(`${Dist}`));
});

gulp.task('clean', () => {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 删除 dist 目录 ...`));
    return del([`${Dist}`]);
});

// 生成 多语言/数据 相关文件
gulp.task('i18nData', function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 生成 i18nData.js ...`));
    return gulp.src([
            srcDataJs,
            srcI18nJs
        ])
        .pipe(concat('i18nData.js'))
        .pipe(gulp.dest(`${Src}/js`));
});

gulp.task('jsHandler', ['i18nData'], function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 处理 JS ...`));
    return gulp.src(srcJs, {
            base: `${Src}`
        })
        .pipe(uglify({
            compress: {
                drop_console: true,
                pure_funcs: ['console.log']
            }
        }))
        .pipe(rev())
        .pipe(revFormat({
            prefix: '.v',
            suffix: '.min'
        }))
        .pipe(gulp.dest(`${Dist}`))
        .pipe(rev.manifest(`${revJs}`))
        .pipe(gulp.dest(`${Build}`));
});

gulp.task('generateCss', function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 处理 Sass, 生成 style.css ...`));
    return gulp.src(srcIndexSass)
        .pipe(sass().on('error', sass.logError))
        .pipe(rename('style.css'))
        .pipe(gulp.dest(`${Src}/theme`));
});

gulp.task('cssHandler', ['generateCss'], function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 处理 CSS ...`));
    return gulp.src(srcStyle, {
            base: `${Src}`
        })
        .pipe(autoprefixer({
            browsers: ['last 2 versions'],
            cascade: false
        }))
        .pipe(cleanCSS({
            compatibility: 'ie8'
        }))
        .pipe(rev())
        .pipe(revFormat({
            prefix: '.v',
            suffix: '.min'
        }))
        .pipe(gulp.dest(`${Dist}`))
        .pipe(rev.manifest(`${revCss}`))
        .pipe(gulp.dest(`${Build}`));
});

gulp.task('generateHtml', function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 生成 index.html ...`));
    return gulp.src(srcPageIndexHtml)
        .pipe(fileinclude({
            prefix: '@@',
            basepath: '@file'
        }))
        .pipe(gulp.dest(`${Src}`));
});

gulp.task('htmlHandler', ['generateHtml'], function() {
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 处理 HTML ...`));
    let options = {
        removeComments: true, // 清除HTML注释
        collapseWhitespace: true, // 压缩HTML
        collapseBooleanAttributes: true, // 省略布尔属性的值 <input checked="true"/> ==> <input />
        removeEmptyAttributes: true, // 删除所有空格作属性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true, // 删除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true, // 删除<style>和<link>的type="text/css"
        minifyJS: true, // 压缩页面JS
        minifyCSS: true, // 压缩页面CSS
        maxLineLength: 150, // 每行允许的最大字符数，会按照可以分割的方式进行分割
        processScripts: ['x-tmpl-mustache'] // 处理内嵌的模板
    };

    return gulp.src([
            buildJson,
            // srcTemplate, // 无需拷贝 template 目录
            srcIndexHtml
        ], {
            base: `${Src}`
        })
        .pipe(revCollector({
            // 与 revFormat 修改的前后缀进行正则匹配
            revSuffix: '\.v[0-9a-f]{8,10}-?\.min'
        }))
        .pipe(htmlmin(options))
        .pipe(gulp.dest(`${Dist}`));
});

// 使用真实的图片素材
gulp.task('use-real-assets', function(){
    console.log(chalk.hex(chalkColorYellow)(`${taskStr} 使用真实的图片素材 ...`));
    return gulp.src([`assets-real/**`]).pipe(gulp.dest(`${Dist}/assets`));
});

// 生成 dist 目录
// -----------------------------------------------------------------------------
gulp.task('build', gulpSequence('simpleCopy', ['jsHandler', 'cssHandler'], 'htmlHandler', 'use-real-assets'));

// serve
// -----------------------------------------------------------------------------
function watcherEventLogger(event) {
    let path = event.path;
    let index = path.indexOf('src');
    path = path.slice(index);
    console.log(
        chalk.hex(chalkColorYellow)(`${watchStr} 文件`) +
        chalk.hex(chalkColorGreen)(` [ ${path} ] `) +
        chalk.hex(chalkColorYellow)(` 发生了改变 ... `)
    );
}

gulp.task('serve-src', function() {
    browserSync.init({
        server: `${Src}`,
        port: PORT
    });

    // 是否是直接监听文件所产生的影响
    let isDirect = false;
    let reloadCount = 0;

    // watch src/page/*.html and src/template/*.mustache, 生成 index.html
    gulp.watch([srcPageIndexHtml, srcTemplate], ['generateHtml']).on('change', (event) => {
        console.log(chalk.hex(chalkColorBlue)(`\n${arrowStr} NO.${reloadCount++} \n${startSpliter}`));
        watcherEventLogger(event);
        isDirect = true;
    });

    // watch src/data/*.js 和 src/i18n/*.js , 生成 i18nData.js
    gulp.watch([srcDataJs, srcI18nJs], ['i18nData']).on('change', (event) => {
        console.log(chalk.hex(chalkColorBlue)(`\n${arrowStr} NO.${reloadCount++} \n${startSpliter}`));
        watcherEventLogger(event);
        isDirect = true;
    });

    // watch src/css/*.scss , 生成 style.css
    gulp.watch(srcSass, ['generateCss']).on('change', (event) => {
        console.log(chalk.hex(chalkColorBlue)(`\n${arrowStr} NO.${reloadCount++} \n${startSpliter}`));
        watcherEventLogger(event);
        isDirect = true;
    });

    // watch html/js/css
    gulp.watch([srcIndexHtml, srcJs, srcStyle], (event) => {
        !isDirect && console.log(chalk.hex(chalkColorBlue)(`\n${arrowStr} NO.${reloadCount++} \n${startSpliter}`));
        watcherEventLogger(event);
        browserSync.reload();

        console.log(chalk.hex(chalkColorPink)(endSpliter));
        isDirect = false;
    });
});

gulp.task('serve-dist', function() {
    browserSync.init({
        server: `${Dist}`,
        port: PORT
    });
});

gulp.task('default', ['serve-src']);
