/*
 * @Author: 莫靓仔
 * @description: 使用gulp压缩文件
 * @Date: 2021-08-26 10:25:20
 * @LastEditors: 莫靓仔
 * @LastEditTime: 2021-09-24 17:43:48
 */
const OUTPUT = './dist'
const fs = require('fs')
const os = require('os')
const del = require('del')
const path = require('path')
const allPath = path.resolve('./')
const distPath = path.resolve(OUTPUT)

const gulp = require('gulp')
const uglify = require('gulp-uglify')
const babel = require('gulp-babel')
const minifyCSS = require('gulp-minify-css')
const imagemin = require('gulp-imagemin')
const htmlmin = require('gulp-htmlmin')
const connect = require('gulp-connect')

// const through = require('through2')
// const browserify = require('browserify')
// const webpack = require('webpack-stream')
// const named = require('vinyl-named')
// const buffer = require('vinyl-buffer')
// const stream = require('vinyl-source-stream')

// 忽略的目录
const ignoreList = [
    path.resolve(OUTPUT),
    path.resolve('./node_modules'),
    path.resolve('./config/tmp'),
    path.resolve('./.vscode'),
    path.resolve('./.git'),
    path.resolve('./package.json'),
    path.resolve('./package-lock.json'),
    path.resolve('./yarn.lock'),
    path.resolve('./yarn-lock.lock')
]
// 忽略函数这些关键字的文件
const ignoreKeyword = [
    'jquery',
    'min',
    'layui',
    'laydate',
    'echarts.js',
    'node_modules',
    'vscode',
    'moment',
    'ecStat'
]

// 获取所有文件路径
const getSrcFile = () => {
    let fileClass = {
        js: [],
        css: [],
        html: [],
        image: [],
        others: []
    }

    /**
     * 获取所有文件的
     * @param filePath 文件夹路径
     * @param status 是否需要打包
     */
    function getAllFile(filePath, status) {
        if (ignoreList.includes(filePath)) {
            return
        }
        let files = fs.readdirSync(filePath)
        files.forEach(file => {
            // 读取所有的文件夹
            let fileDir = path.join(filePath, file)
            let flag = ignoreKeyword.find(item => fileDir.indexOf(item) > -1)
            let fileStat = fs.statSync(fileDir)

            if (fileStat.isDirectory()) {
                // 如果是文件夹 递归获取下面的文件
                // 忽略目录的不打包
                if (ignoreList.includes(fileDir)) {
                    getAllFile(fileDir, false)
                } else {
                    getAllFile(fileDir, status)
                }
            } else if (fileStat.isFile()) {
                if (status && !flag) {
                    // 需要打包的
                    if (/\.js$/.test(file)) {
                        // fileClass.js.push(fileDir)
                        // 因存在es6语法转义之后与commonjs规范冲突的问题尚未解决，暂不压缩js
                        fileClass.others.push(fileDir)
                    } else if (/\.css$/.test(file)) {
                        fileClass.css.push(fileDir)
                    } else if (/\.html$/.test(file)) {
                        fileClass.html.push(fileDir)
                    } else if (
                        /\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$/.test(file)
                    ) {
                        fileClass.image.push(fileDir)
                    } else {
                        // 其他的直接复制，不处理
                        fileClass.others.push(fileDir)
                    }
                } else {
                    fileClass.others.push(fileDir)
                }
            }
        })
    }
    getAllFile(allPath, true)
    return fileClass
}
const { js, css, html, image, others } = getSrcFile()

// 计算每个文件的输出文职
const getOutputPath = filePath => {
    // 区分windows和mac
    let url = os.type() == 'Windows_NT' ? '\\' : '/'
    let res = `${distPath}${allPath.substring(allPath.lastIndexOf(url))}${
        filePath.split(allPath)[1]
    }`
    return res.slice(0, res.lastIndexOf(url))
}

// 编译，打包压缩js
function jsGulp(cb) {
    js.forEach(file => {
        jsTask(file)
    })
    cb()
}
function jsTask(file) {
    let destPath = getOutputPath(file)
    return (
        gulp
            .src(file)
            .pipe(
                babel({
                    presets: [
                        [
                            '@babel/preset-env',
                            {
                                useBuiltIns: false
                            }
                        ]
                    ],
                    plugins: [
                        [
                            '@babel/plugin-transform-runtime',
                            {
                                absoluteRuntime: false,
                                corejs: false,
                                helpers: false,
                                regenerator: true,
                                useESModules: false
                            }
                        ]
                    ]
                })
            )
            // .pipe(
            //     browserify({
            //         entries: file,
            //         debug: true
            //     })
            //         .bundle()
            //         .on('error', function (error) {
            //         })
            //         .pipe(stream(file))
            //         .pipe(buffer())
            // )
            // .pipe(named())
            // .pipe(
            //     webpack({
            //         mode: 'production',
            //         module: {
            //             rules: [
            //                 {
            //                     test: /\.js$/,
            //                     use: [
            //                         {
            //                             loader: 'babel-loader',
            //                             options: {
            //                                 presets: ['@babel/env'],
            //                                 plugins: ['@babel/plugin-transform-runtime']
            //                             }
            //                         }
            //                     ],
            //                     exclude: /node_modules/
            //                 }
            //             ]
            //         }
            //     })
            // )
            .pipe(uglify())
            .pipe(gulp.dest(destPath))
    )
}

// 压缩css
function cssGulp(cb) {
    css.forEach(file => {
        cssTask(file)
    })
    cb()
}
function cssTask(file) {
    let destPath = getOutputPath(file)
    return gulp.src(file).pipe(minifyCSS()).pipe(gulp.dest(destPath))
}

// 压缩图片
function imageGulp(cb) {
    image.forEach(file => {
        imageTask(file)
    })
    cb()
}
function imageTask(file) {
    let destPath = getOutputPath(file)
    return (
        gulp
            .src(file)
            .pipe(
                imagemin({
                    progressive: true
                })
            )
            // .on('error', err => {
            //     imageFlag = false
            // })
            .pipe(gulp.dest(destPath))
    )
    // .on('end', () => {
    // })
}

// 压缩html
function htmlGulp(cb) {
    html.forEach(file => {
        htmlTask(file)
    })
    cb()
}
function htmlTask(file) {
    const htmlOptions = {
        keepClosingSlash: true,
        caseSensitive: true,
        removeComments: true, //清除HTML注释
        collapseWhitespace: true, //压缩HTML
        removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true, //删除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css"
        minifyCSS: true,
        minifyJS: true,
        continueOnParseError: true
    }
    let destPath = getOutputPath(file)
    return gulp.src(file).pipe(htmlmin(htmlOptions)).pipe(gulp.dest(destPath))
}

// 其他文件不作处理，直接复制
function copyGulp(cb) {
    others.forEach(file => {
        copyTask(file)
    })
    cb()
}
function copyTask(file) {
    let destPath = getOutputPath(file)
    // console.log('destPath', destPath)
    return gulp.src(file).pipe(gulp.dest(destPath))
}

// 清除原来的压缩包
function cleanGulp(cb) {
    del.sync(OUTPUT)
    cb()
}

//使用connect启动一个Web服务器
gulp.task('connect', function () {
    connect.server({
        root: './',
        port: 8083,
        livereload: true,
        host:'::'
    })
})

function watchJs() {
    return gulp.watch(['/js/*.js'])
}
function watchCss() {
    return gulp.watch(['/css/*.css'])
}
function watchHtml() {
    return gulp.watch(['/*.html'])
}
gulp.task('watch', function () {
    //livereload.listen();
    gulp.parallel(watchJs, watchCss, watchHtml)
})

gulp.task('dev', gulp.parallel('connect', 'watch'))

// series 串行执行所有任务
// parallel 并行执行所有任务
// 先删除dist文件夹，在执行打包任务（所有打包任务一起执行）
exports.default = gulp.series(
    cleanGulp,
    gulp.parallel(jsGulp, cssGulp, htmlGulp, imageGulp, copyGulp)
)
