var gulp   = require('gulp'),
	rename = require('gulp-rename'),
	uglify = require('gulp-uglify'),
	header = require('gulp-header'),
	concat = require('gulp-concat'),
	replace = require('gulp-replace'),
	fs = require('fs'),

	paths  = {
		componentsFile: 'components.js',
		components: ['components/**/*.js', '!components/**/*.min.js'],
		main: [
			'components/prism-core.js',
			'components/prism-markup.js',
			'components/prism-css.js',
			'components/prism-clike.js',
			'components/prism-javascript.js',
			'plugins/file-highlight/prism-file-highlight.js'
		],
		plugins: ['plugins/**/*.js', '!plugins/**/*.min.js'],
		showLanguagePlugin: 'plugins/show-language/prism-show-language.js',
		autoloaderPlugin: 'plugins/autoloader/prism-autoloader.js',
		changelog: 'CHANGELOG.md'
	};

gulp.task('components', function() {
	return gulp.src(paths.components)
		.pipe(uglify())
		.pipe(rename({ suffix: '.min' }))
		.pipe(gulp.dest('components'));
});

gulp.task('build', function() {
	return gulp.src(paths.main)
		.pipe(header('\n/* **********************************************\n' +
			'     Begin <%= file.relative %>\n' +
			'********************************************** */\n\n'))
		.pipe(concat('prism.js'))
		.pipe(gulp.dest('./'));
});

gulp.task('plugins', ['languages-plugins'], function() {
	return gulp.src(paths.plugins)
		.pipe(uglify())
		.pipe(rename({ suffix: '.min' }))
		.pipe(gulp.dest('plugins'));
});

gulp.task('watch', function() {
	gulp.watch(paths.components, ['components', 'build']);
	gulp.watch(paths.plugins, ['plugins', 'build']);
});

gulp.task('languages-plugins', function (cb) {
	fs.readFile(paths.componentsFile, {
		encoding: 'utf-8'
	}, function (err, data) {
		if (!err) {
			data = data.replace(/^var\s+components\s*=\s*|;\s*$/g, '');
			try {
				data = JSON.parse(data);

				var languagesMap = {};
				var dependenciesMap = {};
				for (var p in data.languages) {
					if (p !== 'meta') {
						var title = data.languages[p].displayTitle || data.languages[p].title;
						var ucfirst = p.substring(0, 1).toUpperCase() + p.substring(1);
						if (title !== ucfirst) {
							languagesMap[p] = title;
						}

						for (var name in data.languages[p].aliasTitles) {
							languagesMap[name] = data.languages[p].aliasTitles[name];
						}

						if(data.languages[p].require) {
							dependenciesMap[p] = data.languages[p].require;
						}
					}
				}

				var jsonLanguagesMap = JSON.stringify(languagesMap);
				var jsonDependenciesMap = JSON.stringify(dependenciesMap);

				var tasks = [
					{plugin: paths.showLanguagePlugin, map: jsonLanguagesMap},
					{plugin: paths.autoloaderPlugin, map: jsonDependenciesMap}
				];

				var cpt = 0;
				var l = tasks.length;
				var done = function() {
					cpt++;
					if(cpt === l) {
						cb && cb();
					}
				};

				tasks.forEach(function(task) {
					var stream = gulp.src(task.plugin)
						.pipe(replace(
							/\/\*languages_placeholder\[\*\/[\s\S]*?\/\*\]\*\//,
							'/*languages_placeholder[*/' + task.map + '/*]*/'
						))
						.pipe(gulp.dest(task.plugin.substring(0, task.plugin.lastIndexOf('/'))));

					stream.on('error', done);
					stream.on('end', done);
				});

			} catch (e) {
				cb(e);
			}
		} else {
			cb(err);
		}
	});
});

gulp.task('changelog', function (cb) {
	return gulp.src(paths.changelog)
		.pipe(replace(
			/#(\d+)(?![\d\]])/g,
			'[#$1](https://github.com/PrismJS/prism/issues/$1)'
		))
		.pipe(replace(
			/\[[\da-f]+(?:, *[\da-f]+)*\]/g,
			function (match) {
				return match.replace(/([\da-f]{7})[\da-f]*/g, '[`$1`](https://github.com/PrismJS/prism/commit/$1)');
			}
		))
		.pipe(gulp.dest('.'));
});

gulp.task('default', ['components', 'plugins', 'build']);
