var walk = require('walk');
var fs = require('fs');
var path = require('path');
var ical = require('ical');
var forEachAsync = require('forEachAsync');
var walker;
var watcher;

var configuration;
var files = [];

exports.start = function(config) {
	configuration = config;

	if(typeof configuration.ignoreDotFiles !== 'undefined' && configuration.ignoreDotFiles == 'false') {
		watcher = require('watch-tree').watchTree(configuration.rootDir, {});
	} else {
		watcher = require('watch-tree').watchTree(configuration.rootDir, {ignore: '.*'});
	}
	watcher.on('fileDeleted', exports.rebuildFiles);
	watcher.on('fileCreated', exports.rebuildFiles);
	watcher.on('fileModified', exports.rebuildFiles);
	exports.rebuildFiles();
};

exports.rebuildFiles = function() {

	console.log('rebuilding...');
	walker = walk.walk(configuration.rootDir, { followLinks: false });

	var newSlides = {};
	walker.on("directories", function (root, dirAr, next) {
	var lastDir = path.join(__dirname, root).split('/');
	if((lastDir.length - __dirname.split('/').length) < 2) {
		dirAr.forEach(function(dir) {
			newSlides[dir.name] = { name: dir.name, template: '', slides: []};
		});
	}
	next();
	}).on("file", function(root, fileStats, next) {
		if(fileStats.name == configuration.descriptionFile || fileStats.name == configuration.eventFile) { 
			next();
		}
		else if(fileStats.name == configuration.templateFile) {
			var lastDir = root.split('/');
			newSlides[lastDir[lastDir.length - 1]]['template'] = path.join(lastDir[lastDir.length - 1], fileStats.name);
			next();
		} else {
			var lastDir = path.join(root).split('/');
			if(newSlides.hasOwnProperty(lastDir[lastDir.length - 1])) {
				var ext = path.extname(fileStats);
				var type = 'image';
				switch (ext) {
					case '.mp4':
					case '.avi':
					case '.ogv':
					case '.mkv':
						type = 'video';
						break;
				}
				newSlides[lastDir[lastDir.length - 1]]['slides'].push({ type: type, file: path.join(lastDir[lastDir.length - 1], fileStats.name), head: '', text: ''});
			}
			next();
		}
	}).on("errors", function(root, nodeStatsArray, next) {
		next();
	}).on("end", function() {
		for(var slideset in newSlides) {
			/* collects descriptions and adds them to the slideset */
			var collectDescs = function(slideset) {
				fs.readFile(path.join(__dirname, configuration.rootDir, slideset, configuration.descriptionFile), function(err, data) {
					if(err) { setSlides(slideset, newSlides[slideset], function(err) { if(err) { throw err}}); return; }
					var descs = JSON.parse(data.toString());
					for(var file in newSlides[slideset]['slides']) {
						if(!newSlides[slideset]['slides'].hasOwnProperty(file)) { continue; }
						if(!newSlides[slideset]['slides'][file].hasOwnProperty('file')) { continue; }
						for(var desc in descs) {
							if(!descs.hasOwnProperty(desc)) { continue; }	
								var comp = newSlides[slideset]['slides'][file]['file'].split('/');
							if(descs[desc]['file'] == comp[comp.length - 1]) {
								newSlides[slideset]['slides'][file]['head'] = descs[desc]['head'];
								newSlides[slideset]['slides'][file]['text'] = descs[desc]['text'];
							}
						}
					}
					setSlides(slideset, newSlides[slideset], function(err) { if(err) { throw err; }});
				});
			}
			/* collect events and adds them to the slideset */
			var collectEvents = function(slideset) {
				fs.readFile(path.join(__dirname, configuration.rootDir, slideset, configuration.eventFile), function(err, data) {
					if(err) { return; }
					try {
						var events = JSON.parse(data.toString());
					} catch(e) {
						return;
					}
					if(events['type'] == 'text') {
						setEvents(slideset, events['events'], function(err) {
							if(err) { throw err; }
						});
					} else if(events['type'] == 'ical') {
						ical.fromURL(events['url'], {}, function(err, bloat) {
							if(err) { throw err; }
							var bDate = new Date();
							var fDate = new Date();
							bDate.setMinutes(bDate.getMinutes() - events['before']);
							fDate.setMinutes(bDate.getMinutes() + events['after']);
							var data = ical.events_between(bDate, fDate);
							var compEv = [];
							for (var k in data) {
								if (!data.hasOwnProperty(k)) { continue; }
								var ev = data[k];
								if(ev.start && ev.summary) {
									var dateStr = ev.start.toLocaleDateString();
									ev.start = ev.start.toLocaleTimeString();
									ev.end = ev.end.toLocaleTimeString();
									delete ev.rrule;
									delete ev.uid;
									delete ev.type;
									for(var i in ev) {
										if(!ev.hasOwnProperty(i)) { continue; }
										if(typeof ev[i] != 'string') { continue; }
										ev[i] = ev[i].replace(/\\,/g, ',');
									}
									if(typeof compEv[dateStr] == "undefined") {
										compEv[dateStr] = [];
									}
									compEv[dateStr].push(ev);
								}
							}
							setEvents(slideset, compEv, function(err) {
								if(err) { throw err; }
							});
						});
					}
				});
			}
			collectDescs(slideset);
			collectEvents(slideset);
		}
	});
};

var setEvents = function(slideset, events, cb) {

	for (var searchset in files) {
		if(!files.hasOwnProperty(searchset)) { continue; }
		if(files[searchset].name == slideset) {
			files[searchset]['events'] = events;
			cb(null);
			return;
		}
	}
	cb('Couldn\'t find slideset');
};

var setSlides = function(slideName, newSlides, cb) {
	files[slideName] = newSlides;
	cb(null);
};

exports.getSlides = function(slideset, cb) {
	
	for (var searchset in files) {
		if(!files.hasOwnProperty(searchset)) { continue; }
		if(files[searchset].name == slideset) {
			cb(null, files[searchset]);
			return;
		}
	}
	cb('Couldn\'t find slideset');
};

exports.getAllSlides = function(cb) {

	var slidesets = [];
	for(var slideset in files) {
		if(!files.hasOwnProperty(slideset)) { continue; }
		slidesets.push(files[slideset].name);
	}
	cb(slidesets);
};