/* jshint node:true */
module.exports = function(grunt) {
	var path = require('path'),
		SOURCE_DIR = 'src/',
		BUILD_DIR = 'build/';

	// Load tasks. 
	require('matchdep').filterDev('grunt-*').forEach( grunt.loadNpmTasks );

	// Project configuration.
	grunt.initConfig({
		clean: {
			all: [BUILD_DIR],
			dynamic: {
				dot: true,
				expand: true,
				cwd: BUILD_DIR,
				src: []
			},
			tinymce: {
				src: [
					'<%= concat.tinymce.dest %>',
					BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce-schema.min.js',
					BUILD_DIR + 'wp-includes/js/tinymce/mark_loaded.js'
				]
			}
		},
		copy: {
			files: {
				files: [
					{
						dot: true,
						expand: true,
						cwd: SOURCE_DIR,
						src: [
							'**',
							'!**/.{svn,git}/**', // Ignore version control directories.
							'!wp-includes/version.php' // Exclude version.php
						],
						dest: BUILD_DIR
					},
					{
						src: 'wp-config-sample.php',
						dest: BUILD_DIR
					}
				]
			},
			version: {
				options: {
					processContent: function( src ) {
						return src.replace( /^(\$wp_version.+?)-src';/m, '$1\';' );
					}
				},
				files: [
					{
						src: SOURCE_DIR + 'wp-includes/version.php',
						dest: BUILD_DIR + 'wp-includes/version.php'
					}
				]
			},
			dynamic: {
				dot: true,
				expand: true,
				cwd: SOURCE_DIR,
				dest: BUILD_DIR,
				src: []
			}
		},
		cssmin: {
			core: {
				expand: true,
				cwd: SOURCE_DIR,
				dest: BUILD_DIR,
				ext: '.min.css',
				src: [
					'wp-admin/css/*.css',
					'wp-includes/css/*.css',
					// Exceptions
					'!wp-admin/css/farbtastic.css'
				]
			}
		},
		jshint: {
			options: grunt.file.readJSON('.jshintrc'),
			grunt: {
				files: {
					src: ['Gruntfile.js']
				},
				options: {
					onevar: true
				}
			},
			tests: {
				files: {
					src: [
						'tests/qunit/**/*.js',
						'!tests/qunit/vendor/qunit.js'
					]
				},
				options: grunt.file.readJSON('tests/qunit/.jshintrc')
			},
			'wp-admin': {
				files: {
					src: [
						'src/wp-admin/js/**/*.js',
						'!src/wp-admin/js/farbtastic.js',
						'!src/wp-admin/js/iris.min.js'
					]
				}
			},
			'wp-includes': {
				files: {
					src: [
						'src/wp-includes/js/**/*.js',
						// 3rd-Party Scripts
						'!src/wp-includes/js/backbone.min.js',
						'!src/wp-includes/js/colorpicker.js',
						'!src/wp-includes/js/crop/**/*.js',
						'!src/wp-includes/js/hoverIntent.js',
						'!src/wp-includes/js/imgareaselect/**/*.js',
						'!src/wp-includes/js/jcrop/**/*.js',
						'!src/wp-includes/js/jquery/**/*.js',
						'!src/wp-includes/js/json2.js',
						'!src/wp-includes/js/mediaelement/**/*.js',
						'!src/wp-includes/js/plupload/**/*.js',
						'!src/wp-includes/js/swfobject.js',
						'!src/wp-includes/js/swfupload/**/*.js',
						'!src/wp-includes/js/thickbox/**/*.js',
						'!src/wp-includes/js/tinymce/**/*.js',
						'!src/wp-includes/js/tw-sack.js',
						'!src/wp-includes/js/underscore.min.js',
						'!src/wp-includes/js/zxcvbn.min.js'
					]
				}
			}
		},
		qunit: {
			files: ['tests/qunit/**/*.html']
		},
		uglify: {
			core: {
				expand: true,
				cwd: SOURCE_DIR,
				dest: BUILD_DIR,
				ext: '.min.js',
				src: [
					'wp-admin/js/*.js',
					'wp-includes/js/*.js',
					'wp-includes/js/plupload/handlers.js',
					'wp-includes/js/plupload/wp-plupload.js',
					'wp-includes/js/tinymce/plugins/wp*/js/*.js',
					'wp-includes/js/tinymce/wp-tinymce-schema.js',
					// Exceptions
					'!wp-admin/js/custom-header.js', // Why? We should minify this.
					'!wp-admin/js/farbtastic.js',
					'!wp-admin/js/iris.min.js',
					'!wp-includes/js/backbone.min.js',
					'!wp-includes/js/swfobject.js',
					'!wp-includes/js/underscore.min.js',
					'!wp-includes/js/zxcvbn.min.js',
					// Hard-coded in editimage.html
					'!wp-includes/js/tinymce/plugins/wpeditimage/js/editimage.js'
				]
			},
			tinymce: {
				expand: true,
				cwd: SOURCE_DIR,
				dest: BUILD_DIR,
				src: [
					'wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js',
					'wp-includes/js/tinymce/plugins/wp*/editor_plugin_src.js',
					'wp-includes/js/tinymce/mark_loaded_src.js'
				],
				// TinyMCE plugins use a nonstandard naming scheme: plugin files are named
				// `editor_plugin_src.js`, and are compressed into `editor_plugin.js`.
				rename: function(destBase, destPath) {
					destPath = destPath.replace(/_src.js$/, '.js');
					return path.join(destBase || '', destPath);
				}
			}
		},
		concat: {
			tinymce: {
				options: {
					separator: '\n',
					process: function( src, filepath ) {
						return '// Source: ' + filepath.replace( BUILD_DIR, '' ) + '\n' + src;
					}
				},
				src: [
					BUILD_DIR + 'wp-includes/js/tinymce/tiny_mce.js',
					BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce-schema.min.js',
					BUILD_DIR + 'wp-includes/js/tinymce/themes/advanced/editor_template.js',
					BUILD_DIR + 'wp-includes/js/tinymce/plugins/*/editor_plugin.js',
					BUILD_DIR + 'wp-includes/js/tinymce/mark_loaded.js'
				],
				dest: BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce.js'
			}
		},
		compress: {
			tinymce: {
				options: {
					mode: 'gzip',
					level: 9
				},
				src: '<%= concat.tinymce.dest %>',
				dest: BUILD_DIR + 'wp-includes/js/tinymce/wp-tinymce.js.gz'
			}
		},
		watch: {
			all: {
				files: [
					SOURCE_DIR + '**',
					// Ignore version control directories.
					'!' + SOURCE_DIR + '**/.{svn,git}/**'
				],
				tasks: ['clean:dynamic', 'copy:dynamic'],
				options: {
					dot: true,
					spawn: false,
					interval: 2000
				}
			},
			test: {
				files: ['tests/qunit/**'],
				tasks: ['qunit']
			}
		}
	});

	// Register tasks.

	// Copy task.
	grunt.registerTask('copy:all', ['copy:files', 'copy:version']);
	
	// Build task.
	grunt.registerTask('build', ['clean:all', 'copy:all', 'cssmin:core', 'uglify:core',
		'uglify:tinymce', 'concat:tinymce', 'compress:tinymce', 'clean:tinymce']);

	// Testing task.
	grunt.registerTask('test', ['qunit']);

	// Default task.
	grunt.registerTask('default', ['build']);

	// Add a listener to the watch task.
	//
	// On `watch:all`, automatically updates the `copy:dynamic` and `clean:dynamic`
	// configurations so that only the changed files are updated.
	grunt.event.on('watch', function( action, filepath, target ) {
		if ( target !== 'all' ) {
			return;
		}

		var relativePath = path.relative( SOURCE_DIR, filepath ),
			cleanSrc = ( action === 'deleted' ) ? [relativePath] : [],
			copySrc = ( action === 'deleted' ) ? [] : [relativePath];

		grunt.config(['clean', 'dynamic', 'src'], cleanSrc);
		grunt.config(['copy', 'dynamic', 'src'], copySrc);
	});
};
