'use strict'

var fs = require('fs')
var print = console.log

// var list1 = []
// function walk(dir, cb) {
// 	var items = fs.readdirSync(dir)
// 	for (var i = 0; i < items.length; i++) {
// 		var fpath = dir + '/' + items[i]
// 		try {
// 			var stat = fs.statSync(fpath)
// 			if (stat.isDirectory()) walk(fpath, cb)
// 			else if (stat.isFile()) list1.push(fpath)
// 		} catch(err) {}
// 	}
// }
// console.time('walk')
// walk('client')
// console.timeEnd('walk')
// print(list1.length)
// print(list1)

var patterns = [
	'client/*',
	'client/*.*',
	'client/*.html',
	'client/google*.html',
	'server/**/*.ts',
	'client/default.html',
	'server/**/*.js',
	'client/{app,components,admin,assets}/**/*.ts',
	'client/{app,components,admin,static}/**/*.jade',
	'client/{app,components}/*/**/*.scss',
	'client/admin/*/**/*.scss',
	'.css/{app,components}/*/**/*.css',
	'.css/admin/*/**/*.css',
	'client/app/**/*.css',
	'.js/app/admin{-routes,.controller}.js',
	'.js/{app,components}/*/**/*.js',
	'client/*.{ico,txt}',
	'client/google*.html',
	'client/assets/js/*.min.js',
	'client/assets/images/*.{png,gif,ico,svg}',
	'client/assets/images/{banner,how_to,map,sprite,shipping,mc}/*.{png,jpg,gif,pdf}',
	'client/assets/fonts/*/*.{eot,ttf,woff}',
	'client/bc/{angular,jquery,ag-grid,masonry,jquery.lazyload,simplemde}/dist/*.min.{js,css}',
	'client/bc/jquery-prettyPhoto/**/*',
	'../doTA.Server/dota-server.js',
	'../doTA.Server/dist/*.min.js',
	'client/{app,admin}/*.{js,css}',
	'client/bc/**/*.{js,css}',
]


function galk(base) {
	var matcher = /(^(?:[^/?*{]+\/)*|\*\*\/|\*\/|[^/]+|\/)/g
	var m = base.match(matcher)
	// print(m)
	var cache = {}
	var list = []

	function _build(p, anchor) {
		var wildcard = 0
		if (~p.indexOf('.'))
			p = p.replace(/\./g, '\\.')
		if (~p.indexOf('**'))
			p = p.replace(/\*\*/g, '.*?'), wildcard = 1
		else if (~p.indexOf('*'))
			p = p.replace(/\*/g, '[^/]*?'), wildcard = 1
		if (~p.indexOf('{'))
			p = p.replace('{', '(?:').replace('}', ')').replace(/,/g, '|'), wildcard = 1
		return wildcard && RegExp(anchor ? '^' + p + '$' : p)
	}

	!function _galk(dir, index, matches, globstar) {
		if (matches[index] === '**/') {
			index++
			globstar = true
		}

		var pathMatcher, fileMatcher, exactMatch
		var star
		if (matches[index] === '*/') {
			index++
			star = true
		} else if (matches[index + 1]) {
			if (~matches[index].indexOf('{') || ~matches[index].indexOf('*')) {
				var cur = matches[index]
				cache[cur] = pathMatcher = cache[cur] || _build(cur, 1)
				// print('pathMatcher', pathMatcher.source)
			} else {
				exactMatch = matches[index]
			}
			index++
			if (matches[index] === '/') index++
		} else if (!matches[index + 1]) {
			if (~matches[index].indexOf('{') || ~matches[index].indexOf('*')) {
				var cur = matches[index]
				cache[cur] = fileMatcher = cache[cur] || _build(cur, 1)
				// print('fileMatcher', fileMatcher.source)
			}
		}


		var items = fs.readdirSync(dir)

		// print(index, dir, matches.slice(index), '**', globstar, '*', star, '{')
		for (var i = 0; i < items.length; i++) {
			var fpath = (dir[dir.length - 1] === '/' ? dir : dir + '/') + items[i]
			try {
				var stat = fs.statSync(fpath)
				// print(fpath, items[i], stat.isFile(), stat.isDirectory(), globstar, star)
				if (stat.isFile()) {
					// print('isFile', fpath, items[i], matches.slice(index), cur)
					if (items[i] === matches[index] || (fileMatcher && fileMatcher.test(items[i]))) {
						list.push(fpath)
					}
				} else if (stat.isDirectory()) {
					if (globstar) {
						// print('globstar', fpath, index, matches.slice(index), globstar)
						_galk(fpath, index, matches, globstar)
					} else if (star) {
						// print('star', fpath, items[i], globstar, star)
						_galk(fpath, index, matches, globstar)
					} else if (pathMatcher && pathMatcher.test(items[i])) {
						// print('multiple', fpath, items[i], globstar, star)
						_galk(fpath, index, matches, globstar)
					} else if (exactMatch && items[i] === exactMatch) {
						// print('exact', fpath, items[i], globstar, star)
						_galk(fpath, index, matches, globstar)
					}
				}
			} catch(err) {
				if (err.code !== 'ENOENT')
					process.stderr.write('[' + err.code + ']:' + fpath + '\n')
			}
		}
	}(m[0] || '.', 1, m)

	return list
}

var glob = require('glob')

for (var i = 0, x; x = patterns[i]; i++) {
	print('\t', x)

	console.time('galk')
	var list3 = galk(x)
	console.timeEnd('galk')
	// print(list3)
// }
// print("=======================")
// for (var i = 0, x; x = patterns[i]; i++) {
	console.time('glob')
	var list2 = glob.sync(x)
	console.timeEnd('glob')
	// print(list2)

	if (list3.length !== list2.length) {
		print(list3.slice(0, 1), list3.length)
		print(list2.slice(0, 1), list2.length)
	}
}
