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

var configuration;
var files = [];

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

	if(configuration.ignoreDotFiles == 'false') {
		watcher = require('watch-tree').watchTree(configuration.rootDir, {});
	} else {
		watcher = require('watch-tree').watchTree(configuration.rootDir, {ignore: '.*'});
	}
	if(typeof configuration.fetchInterval == 'number' && configuration.fetchInterval > 0) {
		setInterval(fetchAllEvents, configuration.fetchInterval);
	}
	watcher.on('fileDeleted', rebuildFiles);
	watcher.on('fileCreated', rebuildFiles);
	watcher.on('fileModified', rebuildFiles);
	rebuildFiles();
	setTimeout(fetchAllEvents, 2000);
};

var rebuildFiles = function() {
	configuration.logger.inf('Rebuilding slideset database...');
	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; }});
				});
			}
			collectDescs(slideset);
		}
	});
};

var fetchAllEvents = function() {
	configuration.logger.inf('Fetching all events...');
	exports.getAllSlides(function(Slides) {
		for(var slideset in Slides) {
			if(!Slides.hasOwnProperty(slideset)) { continue; }
			fetchEvents(Slides[slideset]);
		}
	});
};

/* collect events and adds them to the slideset */
var fetchEvents = function(slideset) {
	configuration.logger.inf('Fetching ' + 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; }
				});
			});
		}
	});
};

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);
};