"use strict";
var fs = require( 'fs' ),
    path = require( 'path' ),
    gulp = require( 'gulp' ),
    clean = require( 'gulp-clean' ), //- 删除文件
    cleanCss = require( 'gulp-clean-css' ), //- 压缩CSS为一行;
    concat = require( 'gulp-concat' ), //- 多个文件合并为一个;
    cssSprite = require( 'gulp-css-spritesmith' ), //- css雪碧图
    imagemin = require( 'gulp-imagemin' ), //- 图片压缩
    rename = require( 'gulp-rename' ), //- 合并文件夹
    replace = require( 'gulp-replace' ), //- 替换文件内容
    rjs = require( 'gulp-requirejs-optimize' ), //- requirejs合并
    rev = require( 'gulp-rev' ), //- 对文件名加MD5后缀
    revCollector = require( 'gulp-rev-collector' ), //- md5路径替换
    sass = require( 'gulp-sass' ), //- scss编译
    gulpSequence = require( 'gulp-sequence' ), //- 顺序执行命令
    uglify = require( 'gulp-uglify' ), //- 压缩js
    pngquant = require( 'imagemin-pngquant' ); //- 深度压缩

/**
 * 工具函数
 */
var util = {
    //创建文件夹（使用时第二个参数可以忽略）
    mkdir: function( dirpath, dirname ) {
        //判断是否是第一次调用
        if ( typeof dirname === "undefined" ) {
            if ( fs.existsSync( dirpath ) ) {
                return;
            } else {
                util.mkdir( dirpath, path.dirname( dirpath ) );
            }
        } else {
            //判断第二个参数是否正常，避免调用时传入错误参数
            if ( dirname !== path.dirname( dirpath ) ) {
                util.mkdir( dirpath );
                return;
            }
            if ( fs.existsSync( dirname ) ) {
                fs.mkdirSync( dirpath );
            } else {
                util.mkdir( dirname, path.dirname( dirname ) );
                fs.mkdirSync( dirpath );
            }
        }
    }
};
/**
 * 全局参数
 */
//项目名称
var projectName = '{$projectName}';

//默认模式：测试模式
var mode = ""; //测试模式：null；发布模式：release

//项目是否使用requireJs
var isRequireJs = true;

//项目文件路径
var cssSrc = './static/',
    jsSrc = './static/',
    tplSrc = './template/';

//发布路径
var cssDest = '../../web/img1.37wanimg.com/' + projectName + '/',
    jsDest = '../../web/ptres.37.com/js/' + projectName + '/',
    tplDest = '../../web/common.tpl.37.com/' + projectName + '/';

//命令接收的参数
var param = process.argv,
    taskName = param[ 2 ],
    taskValue = param[ 3 ];

var projectModule = ""; //频道名

if ( taskValue ) {
    projectModule = taskValue.substr( 1 );
} else {
    return console.error( "请输入您要处理的频道名！" );
}

/**
 * 注册任务
 * 
 * 1，频道目录创建 √（dir）
 * 2，模板文件复制 √（tpl）
 * 3，样式和图片处理
 * 3.1，scss文件编译 √（spriteScss）
 * 3.2，复制css文件到临时目录 √（spriteCss）
 * 3.3，复制img文件到临时目录 √（spriteImg）
 * 3.4，制作雪碧图（测试流程不创建时间戳文件名的雪碧图文件） √（spriteDest）
 * 3.5，合并css，同时换css的图片路径，复制到发布目录 √（sCopyCss）
 * 3.6，合并好的雪碧图和频道里不用合并的图片，复制到发布目录，同时压缩img文件 √（sCopyImg）
 * 3.7，清除css和img临时目录 √（cleanSprite）
 * 4，js处理
 * 4.1，使用rjs进行js合并，复制到发布目录 √（js）
 * 4.2，普通js合并，复制到发布目录 √（js）
 * 5，自动上传测试机
 * 6，上线流程
 * 6.1，压缩文件
 * 6.1.1，压缩css文件，同时复制成加了md5戳的文件 √（cleanCss）
 * 6.1.2，压缩js文件，同时复制成加了md5戳的文件 √（uglifyJs）
 * 6.2，修改模板文件名
 * 6.2.1，修改模板里的css文件名 √（r_css）
 * 6.2.2，修改模板里的js文件名 √（r_js）
 * 6.2.3，根据新建好的文件修改模板里的文件名 √（r_tpl）
 */
//1 创建频道目录
gulp.task( 'dir', function() {
    util.mkdir( tplSrc + "home/" + projectModule + "/images" );
    util.mkdir( tplSrc + "home/" + projectModule + "/images_" );
    util.mkdir( tplSrc + "modules/" + projectModule );
} );
//2 复制模板覆盖到common.tpl.37.com
gulp.task( 'tpl_home', function( cb ) {
    return gulp.src( tplSrc + "home/" + projectModule + "/*" )
        .pipe( replace( /\/debug\//g, '/' ) )
        .pipe( replace( /\?\{\{\$smarty\.now\}\}/g, '' ) )
        .pipe( gulp.dest( tplDest + "home/" + projectModule + "/" ) );
} );
gulp.task( 'tpl_modules', function( cb ) {
    return gulp.src( tplSrc + "modules/" + projectModule + "/**/*" )
        .pipe( replace( /\/debug\//g, '/' ) )
        .pipe( replace( /\?\{\{\$smarty\.now\}\}/g, '' ) )
        .pipe( gulp.dest( tplDest + "modules/" + projectModule + "/" ) );
} );
gulp.task( 'tpl', function( cb ) {
    var src, dest, src_array = [];
    if ( projectModule === "common" ) {
        src = tplSrc + projectModule + "/*";
        dest = tplDest + projectModule + "/";
        //复制文件
        return gulp.src( src )
            .pipe( replace( /\/debug\//g, '/' ) )
            .pipe( replace( /\?\{\{\$smarty\.now\}\}/g, '' ) )
            .pipe( gulp.dest( dest ) );
    } else {
        gulpSequence( 'tpl_home', 'tpl_modules' )( function( err ) {
            if ( err ) console.log( err )
        } );
    }
    /*fs.stat( src, function( err, stat ) {
        if ( err == null ) {
            if ( stat.isDirectory() ) {
                //复制文件
                gulp.src( src_array )
                    .pipe( replace( /\/debug\//g, '/' ) )
                    .pipe( replace( /\?\{\{\$smarty\.now\}\}/g, '' ) )
                    .pipe( gulp.dest( tplDest ) );
            } else if ( stat.isFile() ) {
                console.log( '这是文件' );
            } else {
                console.log( stat + '路径存在，但既不是文件，也不是文件夹' );
            }
        } else if ( err.code == 'ENOENT' ) {
            console.log( '路径不存在： ' + err.name );
        } else {
            console.log( '错误： ' + err );
        }
    } );*/
} );

//3 处理雪碧图、合并图片至img1.37wanimg.com/{$projectName}/debug/{css,images}
//3.1 编译scss
gulp.task( 'spriteScss', function( cb ) {
    var src = [];
    if ( projectModule === "common" ) {
        src.push( cssSrc + projectModule + '/**/*.scss' );
    } else {
        src.push( cssSrc + "home/" + projectModule + '/**/*.scss' );
        src.push( cssSrc + "modules/" + projectModule + '/**/*.scss' );
    }
    return gulp.src( src )
        .pipe( sass().on( 'error', sass.logError ) )
        .pipe( gulp.dest( 'spriteScss' ) );
} );
//3.2 复制合并css
gulp.task( 'spriteCss', function( cb ) {
    var src = [];
    if ( projectModule === "common" ) {
        src.push( cssSrc + projectModule + '/**/*.css' );
        src.push( '!' + cssSrc + projectModule + '/**/_*.css' );
    } else {
        src.push( cssSrc + "home/" + projectModule + '/**/*.css' );
        src.push( '!' + cssSrc + "home/" + projectModule + '/**/_*.css' );
        src.push( cssSrc + "modules/" + projectModule + '/**/*.css' );
        src.push( '!' + cssSrc + "modules/" + projectModule + '/**/_*.css' );
    }
    src.push( 'spriteScss/**/*.css' );
    //- 创建一个名为 concat 的 task
    return gulp.src( src )
        //- 合并后的文件名
        .pipe( concat( projectModule + '.css' ) )
        .pipe( replace( /\(images\//g, '(../spriteImg/' ) )
        //- 输出文件本地
        .pipe( gulp.dest( 'spriteCss' ) );
} );

//3.3 复制images
gulp.task( 'spriteImg', function( cb ) {
    var img = [ "png", "jpg", "gif" ],
        src = [],
        add = function( f ) {
            var i = 0;
            for ( i; i < img.length; i++ ) {
                src.push( f + "*." + img[ i ] );
            }
        };
    if ( projectModule === "common" ) {
        add( cssSrc + projectModule + '/**/images/' );
    } else {
        add( cssSrc + "home/" + projectModule + '/**/images/' );
        add( cssSrc + "modules/" + projectModule + '/**/images/' );
    }
    return gulp.src( src )
        .pipe( rename( {
            dirname: ''
        } ) )
        .pipe( imagemin( {
            optimizationLevel: 3, //类型：Number  默认：3  取值范围：0-7（优化等级）
            progressive: true, //类型：Boolean 默认：false 无损压缩jpg图片
            interlaced: true, //类型：Boolean 默认：false 隔行扫描gif进行渲染
            multipass: true //类型：Boolean 默认：false 多次优化svg直到完全优化
        } ) )
        .pipe( gulp.dest( 'spriteImg' ) );
} );

//3.4 生成雪碧图(使用根目录文件夹)
gulp.task( 'spriteDest', function( cb ) {
    return gulp.src( 'spriteCss/' + projectModule + '.css' )
        .pipe( cssSprite( {
            // sprite背景图源文件夹，只有匹配此路径才会处理，默认 ./static/pay/images/
            imagepath: 'spriteImg/',
            // 映射CSS中背景路径，支持函数和数组，默认为 null
            imagepath_map: null,
            // 雪碧图输出目录，注意，会覆盖之前文件！默认 images/
            spritedest: 'spriteImg/',
            // 替换后的背景路径，默认 ../images/
            spritepath: '../images/' + projectModule + '/',
            // 各图片间间距，如果设置为奇数，会强制+1以保证生成的2x图片为偶数宽高，默认 0
            padding: 2,
            // 是否使用 image-set 作为2x图片实现，默认不使用
            useimageset: false,
            // 是否以时间戳为文件名生成新的雪碧图文件，如果启用请注意清理之前生成的文件，默认不生成新文件
            newsprite: mode === "release", //判断是否发布模式，是就建以时间戳为文件名的文件，否则不建。
            // 给雪碧图追加时间戳，默认不追加
            spritestamp: false,
            // 在CSS文件末尾追加时间戳，默认不追加
            cssstamp: false
        } ) )
        .pipe( gulp.dest( 'spriteDest/' ) );
} );

//3.5 合并css
gulp.task( 'sCopyCss', function( cb ) {
    return gulp.src( 'spriteDest/spriteCss/' + projectModule + '.css' )
        .pipe( replace( /images_\//g, '../images/' + projectModule + '/' ) )
        .pipe( gulp.dest( cssDest + '/css/' ) );
} );

//3.6 复制img
gulp.task( 'sCopyImg', function( cb ) {
    var img = [ "png", "jpg", "gif" ],
        src = [],
        add = function( f ) {
            var i = 0;
            for ( i; i < img.length; i++ ) {
                src.push( f + "*." + img[ i ] );
            }
        };
    src.push( './spriteDest/spriteImg/*.png' );
    if ( projectModule === "common" ) {
        add( cssSrc + projectModule + '/**/images_/' );
    } else {
        add( cssSrc + "home/" + projectModule + '/**/images_/' );
        add( cssSrc + "modules/" + projectModule + '/**/images_/' );
    }
    return gulp.src( src )
        .pipe( rename( {
            dirname: ''
        } ) )
        .pipe( imagemin( {
            optimizationLevel: 3, //类型：Number  默认：3  取值范围：0-7（优化等级）
            progressive: true, //类型：Boolean 默认：false 无损压缩jpg图片
            interlaced: true, //类型：Boolean 默认：false 隔行扫描gif进行渲染
            multipass: true //类型：Boolean 默认：false 多次优化svg直到完全优化
        } ) )
        .pipe( imagemin( {
            progressive: true, // 无损压缩JPG图片
            svgoPlugins: [ {
                removeViewBox: false
            } ], // 不移除svg的viewbox属性
            use: [ pngquant() ] // 使用pngquant插件进行深度压缩
        } ) )
        .pipe( gulp.dest( cssDest + '/images/' + projectModule + '/' ) );
} );

//3.7 删除临时文件
gulp.task( 'cleanSprite', function( cb ) {
    console.log( "删除冗余图片！" );
    return gulp.src( [ './spriteScss', './spriteCss', './spriteImg', './spriteDest' ] )
        .pipe( clean( {
            force: true
        } ) );
} );

//完成 CSS\Images的发布 spriteScss->spriteCss->spriteImg->spriteDest->(sCopyCss,sCopyImg)->cleanSprite
gulp.task( 'css', gulpSequence( 'spriteScss', 'spriteCss', 'spriteImg', 'spriteDest', [ 'sCopyCss', 'sCopyImg' ], 'cleanSprite', function() {
    console.log( "输出完成！" );
} ) );

//4 js发布
gulp.task( 'createCJs', function() {
    console.log( "创建common.js,此文件合并用！" );
    /*return gulp.src( './static/common/order.js' )
        .pipe( concat( 'common.js' ) )
        .pipe( gulp.dest( './static/' ) );*/
} );

gulp.task( 'compile_js', function( cb ) {
    if ( isRequireJs ) {
        //4.1 使用rjs进行js合并，复制到发布目录
        return gulp.src( jsSrc + '/home/' + projectModule + '/' + projectModule + '.js' )
            .pipe( rjs( function( file ) {
                return {
                    name: 'home/' + projectModule + '/' + projectModule,
                    optimize: 'none',
                    useStrict: true,
                    baseUrl: 'static/',
                    include: null,
                    exclude: [ 'common' ]
                };
            } ) )
            .pipe( gulp.dest( jsDest ) );
    } else {
        //4.2 普通js合并，复制到发布目录
        var src = [];
        if ( projectModule === "common" ) {
            src.push( cssSrc + projectModule + '/**/*.js' );
            src.push( cssSrc + "modules/" + projectModule + '/**/*.js' );
        } else {
            src.push( cssSrc + "home/" + projectModule + '/**/*.js' );
            src.push( cssSrc + "modules/" + projectModule + '/**/*.js' );
        }
        return gulp.src( src )
            //- 合并后的文件名
            .pipe( concat( projectModule + '.js' ) )
            //.pipe( replace( /\(images\//g, '(../spriteImg/' ) )
            //- 输出文件
            .pipe( gulp.dest( jsDest ) );
    }
} );

//4.1|4.2 处理js后复制到ptres.37.com/js/{$projectName}/
gulp.task( 'js', gulpSequence( 'createCJs', 'compile_js' ) );

//6.1.1 压缩css并添加MD5戳至img1.37wanimg.com/{$projectName}/css/
gulp.task( 'cleanCss', function( cb ) {
    //- 需要处理的css文件，放到一个字符串数组里
    return gulp.src( [ cssDest + '/css/' + projectModule + '.css' ] )
        //- 压缩处理成一行
        .pipe( cleanCss( {
            compatibility: 'ie7'
        } ) )
        //- 文件名加MD5后缀
        .pipe( rev() )
        //- 输出文件本地
        .pipe( gulp.dest( cssDest + '/css/' ) )
        //- 生成一个rev-manifest.json
        .pipe( rev.manifest() )
        //- 将 rev-manifest.json 保存到 rev 目录内
        .pipe( gulp.dest( './rev/css/' + projectModule ) );
} );

//6.1.2 压缩js并添加MD5戳至ptres.37.com/js/{$projectName}/
gulp.task( 'uglifyJs', function( cb ) {
    //- 需要处理的js文件，放到一个字符串数组里
    return gulp.src( [ jsDest + '/' + projectModule + '.js' ] )
        //- 压缩处理成一行
        .pipe( uglify() )
        //- 文件名加MD5后缀
        .pipe( rev() )
        //- 输出文件本地
        .pipe( gulp.dest( jsDest ) )
        //- 生成一个rev-manifest.json
        .pipe( rev.manifest() )
        //- 将 rev-manifest.json 保存到 rev 目录内
        .pipe( gulp.dest( './rev/js/' + projectModule ) );
} );

//6.2.1 css时间戳替换
gulp.task( 'tpl_css', function( cb ) {
    return gulp.src( [ './rev/css/' + projectModule + '/*.json', tplDest + '/**/*.htm' ] ) //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe( revCollector( {
            replaceReved: true
        } ) )
        .pipe( gulp.dest( tplDest ) ); //- 替换后的文件输出的目录
} );

gulp.task( 'r_css', gulpSequence( 'css', 'cleanCss', 'tpl_css', function() {
    console.log( "产出css完成，模板时间戳已更新！" );
} ) );

//6.2.2 js时间戳替换
gulp.task( 'tpl_js', function( cb ) {
    return gulp.src( [ './rev/js/' + projectModule + '/*.json', tplDest + '/**/*.htm' ] ) //- 读取 rev-manifest.json 文件以及需要进行js名替换的文件
        .pipe( revCollector( {
            replaceReved: true
        } ) )
        .pipe( gulp.dest( tplDest ) ); //- 替换后的文件输出的目录
} );

gulp.task( 'r_js', gulpSequence( 'js', 'uglifyJs', 'tpl_js', function() {
    console.log( "产出js完成，模板时间戳已更新！" );
} ) );

//6.2.3 发布模板
gulp.task( 'tpl_tpl', function( cb ) {
    return gulp.src( [ './rev/*/' + projectModule + '/*.json', tplDest + '/**/*.htm' ] ) //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
        .pipe( revCollector( {
            replaceReved: true
        } ) )
        .pipe( gulp.dest( tplDest ) ); //- 替换后的文件输出的目录
} );

gulp.task( 'r_tpl', gulpSequence( 'tpl', 'tpl_tpl', function() {
    console.log( "模板时间戳已更新！" );
} ) );

//单频道发布
gulp.task( 'rev', gulpSequence( [ 'tpl', 'r_js', 'r_css' ] ) );

/**
 * 命令说明
 * 1,命令：gulp dir -(频道名)
 *   说明：创建项目里的频道目录
 *   例子：gulp dir -index
 * 
 * 2,模板类：
 * 2.1,命令：gulp tpl -(频道名)
 *     说明：将某频道里的模板复制到发布目录
 *     例子：gulp tpl -index
 * 2.2,命令：gulp r_tpl:(频道名)
 *     说明：将某频道里的模板复制到发布目录后，修改模板里的js/css文件名为加了md5戳的名字
 *     例子：gulp r_tpl -index
 * 
 * 3,css类：
 * 3.1,命令：gulp css -(频道名)
 *     说明：将某频道里的css和img发布到发布目录
 *     例子：gulp css -index
 * 3.2,命令：gulp r_css -(频道名)
 *     说明：将某频道里的css和img发布到发布目录后，修改模板里的css文件名为加了md5戳的名字
 *     例子：gulp r_css -index
 * 
 * 4,js类：
 * 4.1,命令：gulp js -(频道名)
 *     说明：将某频道里的js发布到发布目录
 *     例子：gulp js -index
 * 4.2,命令：gulp r_js -(频道名)
 *     说明：将某频道里的js发布到发布目录后，修改模板里的js文件名为加了md5戳的名字
 *     例子：gulp r_js -index
 * 
 * 5,命令：gulp rev -(频道名)
 *   说明：将某个频道里的模板、css、img、js都发布到发布目录，再修改模板的文件名
 *   例子：gulp rev -index
 */