#!/usr/bin/env node
// https://gist.github.com/dimitarcl/3767879
var fs = require('fs')

var functionName = /^\s+\/\/\/\s+@function\s+(.*)$/;
var type = /^(\s+)\/\/\/\s+@param\s+{(\w*)}\s+(.+?)(\s+.*)$/;
var param = /^(\s+)\/\/\/\s+@param\s+(.+?)\s/;
var resultType = /^(\s+)\/\/\/\s+@return\s+{(\w+)}(\s+.*)$/;

function Section()
{
	this.name = '';
	this.result = 'undefined';
	this.args = [];
	this.comments = [];
	this.namespaces = [];
}

Section.prototype.handle_function = function (line) {
	this.namespaces = line.match(functionName)[1].split('.') || [];
	this.name = this.namespaces.pop();
};

Section.prototype.handle_param = function (line) {
	var paramType = 'Object';
	var name = '';
	var m = line.match(type);
	var r = line;
	if (m) {
		paramType = m[2];
		name = m[3];
		r = m[1] + '/// @param ' + name + m[4];
	}
	else {
		m = line.match(param);
		name = m[2];
	}
	this.args.push({name: name, type: paramType});
	this.comments.push(r);
};

Section.prototype.handle_return = function (line) {
	this.result = 'undefined';
	var m = line.match(resultType);
	var r = line;
	if (m) {
		this.result = m[2];
		r = m[1] + '/// @return ' + m[3];
	}
	this.comments.push(r);
};

Section.prototype.Generate = function () {
	var doc = [];

	this.namespaces.forEach(function (namespace) {
		doc.push('namespace ' + namespace + ' {\n');
	});

	this.comments.forEach(function (c) {
		doc.push(c);
	});

	var args = [];

	this.args.forEach(function (argument) {
		args.push(argument.type + ' ' + argument.name);
	});

	if (this.name) {
		doc.push(this.result + ' ' + this.name + '(' + args.join(', ') + ');');
	}

	this.namespaces.forEach(function (namespace) {
			doc.push('}\n');
	});
	return doc.join('\n');
};

Section.prototype.handle_line = function (line) {
	this.comments.push(line);
};

function writeLine(line) {
	process.stdout.write(line + '\n');
}

fs.readFile(process.argv[2], 'utf8', function (err, data) {
	var lines = data.split('\n');
	var comment = /^\s*\/\/\//;
	var directive = /@(\w+)\s+(.*)$/;
	var inside = false;
	var section = new Section();
	lines.forEach(function(line) {
		if (line.match(comment)) {
			var d = line.match(directive);
			if (d) {
				var handle = Section.prototype['handle_' + d[1]] || Section.prototype.handle_line;
				handle.call(section, line);
			} else {
				section.handle_line(line);
			}
			inside = true;
		} else if (inside) {
			writeLine(section.Generate());
			inside = false;
			section = new Section();
		}
	});
});
