// Command line: 
// From jquery/jquery
// java -cp build/docs/itext-1.4.8.jar:build/js.jar org.mozilla.javascript.tools.shell.Main build/docs/docs_pdf.js dist/jquery.js `find ../plugins/ -name "*.js" -print` build/docs

importPackage(java.io);
var pdf = {
	Color : java.awt.Color,
	Document : Packages.com.lowagie.text.Document,
	Writer : Packages.com.lowagie.text.pdf.PdfWriter,
	Paragraph : Packages.com.lowagie.text.Paragraph,
	Chapter : Packages.com.lowagie.text.Chapter,
	Chunk : Packages.com.lowagie.text.Chunk,
	Element : Packages.com.lowagie.text.Element,
	Font : Packages.com.lowagie.text.Font,
	FontFactory : Packages.com.lowagie.text.FontFactory,
	// To avoid ambigious method signitures:
	getFont : Packages.com.lowagie.text.FontFactory["getFont(java.lang.String,float,int,java.awt.Color)"],
	PageSize : Packages.com.lowagie.text.PageSize,
	Section : Packages.com.lowagie.text.Section,
	Image : Packages.com.lowagie.text.Image,
	init : function (pdfname, title) {
	//	this.doc = new this.Document(this.PageSize.A4, 50, 50, 50, 50);
        this.doc = new this.Document();
		this.writer = this.Writer.getInstance(this.doc,
							new FileOutputStream(pdfname));
		this.writer.setViewerPreferences(this.Writer.PageModeUseOutlines);
		this.titleFont = this.getFont(this.FontFactory.HELVETICA, 22.0, this.Font.BOLD, this.Color.BLACK);
		this.chapterFont = this.getFont(this.FontFactory.HELVETICA, 16.0, this.Font.BOLD, this.Color.BLACK);
		this.sectionFont = this.getFont(this.FontFactory.COURIER, 14.0, this.Font.NORMAL, this.Color.RED);
		this.paramFont = this.getFont(this.FontFactory.COURIER, 14.0, this.Font.NORMAL, this.Color.GRAY);
		this.headerFont = this.getFont(this.FontFactory.HELVETICA, 14.0, this.Font.BOLD, this.Color.BLUE);
		this.bodyFont = this.getFont(this.FontFactory.HELVETICA, 12.0, this.Font.NORMAL, this.Color.BLACK);
		this.syntaxFont =  this.getFont(this.FontFactory.COURIER, 10.0, this.Font.NORMAL, this.Color.BLACK);
		// set the title:
		var title = "JQuery " + readFile('version.txt');
		if (arguments.length > 1)
			title += ' with official plugins';
		pdf.doc.addTitle(title);
		this.doc.open();
	},
	chapterCount : 0
};
load("build/js/writeFile.js", "build/js/parse.js", "build/js/json.js");
if (arguments.length < 2) {
	print("Usage: scriptname jquery_src [plugin1_src plugin2_src ...] pdf_output_dir");
	quit();
}

var outputfile = arguments.pop();  // the last argument is the output file  

// Read all the arguments - hopefully both JQuery and plugins...
var src;
var all = [];
while(src=arguments.shift()) {
	print("parsing file " + src);
	var c = parse( read(src) );
	if (typeof c == 'object' && c.length && c.length > 0) {
		c.forEach(function(item){ all.push(item); });
		print("Found " + c.length + " items in " + c[0].cat);
	}
}
all = categorize( all );

// set the title:
var title = "JQuery " + readFile('version.txt').replace(/\n/g, "");
all.cat.forEach(
	function(category){ 
		if (category.value == 'Plugins')
			title += ' with official plugins';
	});

pdf.init(outputfile, title);
makeCoverPage(pdf, title);


//print(Object.toJSON(all));
all.cat.forEach(function(category) {
	print("Writing Category " + category.value + "\n");
	writeChapter(pdf, category);
	});

pdf.doc.close();
//~ writeFile( dir + "pdf.log", log );
//~ c = categorize( c );
//~ output( c, "cat" );

function writeChapter(pdf, cat) {
	var cat_title = new pdf.Paragraph(cat.value, pdf.chapterFont);
	var chapter = new pdf.Chapter(cat_title, ++pdf.chapterCount);
	if (cat.cat && cat.cat.length > 0) {
		cat.cat.forEach(function(subcat) {
			print("\tWriting Sub-Category " + subcat.value + "\n");
			var subtitle = new pdf.Paragraph(subcat.value, pdf.chapterFont);
			var sub_chapter = chapter.addSection(subtitle, 0);
			writeMethods(pdf, subcat.method, sub_chapter);
				} );
	}
	writeMethods(pdf, cat.method, chapter);
	pdf.doc.add(chapter);
}

function writeMethods(pdf, methods, chapter) {
	var name = undefined;
	var section = undefined;
	methods.forEach( function(method) {
				if (method['private']) 
					return;
				var method_brief = methodBriefSig(method);
				if (name != method_brief) {
					if (section) {
						section.add(pdf.Chunk.NEXTPAGE);
					}
					section = chapter.addSection(new pdf.Paragraph(method_brief, pdf.chapterFont), 0);
					name = method_brief;
				}
				var methodSig = makeSignature(method, pdf);
				section.add(methodSig);
				var desc_text = fixText(method.desc)
								.replace(/\n\n/g, '\\n')
								.replace(/\n(\t|\s\s)/g, '\\n$1')
								.replace(/\n/g, ' ')
								.replace(/\\n/g, "\n");
				//var desc = new pdf.Paragraph(fixText(method.desc).replace(/\n/g, " "), pdf.bodyFont);
				var desc = new pdf.Paragraph(desc_text, pdf.bodyFont);
				desc.setSpacingBefore(15);
				//~ if (method.desc != method['short']) {
					//~ var brief = new pdf.Paragraph(fixText(method['short']).replace(/\n/g, " "), pdf.briefFont);
					//~ section.add(brief);
				//~ }
				section.add(desc);
				if (method && method.examples && method.examples.length > 0) {
				var examp = makeExamples(pdf, method.examples);
			//~ print(examp.length);
				examp.forEach( function(example) {
								example.setSpacingBefore(16);
								section.add(example);
							});
				}
			} );
}

function methodBriefSig(method) {
	return method.name + '(' + method.params.map(function(p){return p.type;}) + ')';
}

function makeSignature(method, pdf){
	//~ var p = new pdf.Paragraph();
	//~ var nm = var c = new pdf.Chunk(fixText(ex.result), pdf.syntaxFont);
	var sig = method.name + '(';
	if (method.params) {
		for (var i=0;i<method.params.length;i++){
			var param = method.params[i];
			sig += fixText(param.type) + ' ' + fixText(param.name);
			if (i < method.params.length-1)
				sig+= ', ';
		}
	}
	sig += ') returns ' + fixText(method.type);
	return new pdf.Paragraph(sig, pdf.sectionFont);
}

function fixText(text){
	if (text == undefined ){
		return('');
	}
	var t = text
		.replace(/&lt;/g, "<")
		.replace(/&gt;/g, ">")
		.replace(/&amp;/g, "&");
	return t;
}

function makeExamples(pdf, examples){
	var exp = [  ];
	for(var i = 0; i<examples.length;i++) {
		var ex = examples[i];
		if (ex.code) {
			exp.push(new pdf.Paragraph('Example:', pdf.headerFont));
			if (ex.desc) {
				//~ print(ex.code + "\n" + ex.desc);
				exp.push(new pdf.Paragraph(fixText(ex.desc).replace(/\n/g, " "), pdf.bodyFont));
			}
			var p = new pdf.Paragraph(fixText(ex.code), pdf.syntaxFont);
			p.setIndentationLeft(10);
			exp.push(p);
		}
		if (ex.before) {
			exp.push(new pdf.Paragraph('HTML:', pdf.headerFont));
			var p = new pdf.Paragraph(fixText(ex.before), pdf.syntaxFont);
			p.setIndentationLeft(10);
			exp.push(p);
		}
		if (ex.result) {
			exp.push(new pdf.Paragraph('Result:', pdf.headerFont));
			var p = new pdf.Paragraph(fixText(ex.result), pdf.syntaxFont);
			p.setIndentationLeft(10);
			exp.push(p);
		}
	}
	return(exp);
}

function makeCoverPage(pdf, title) {
	var top = new pdf.Paragraph(title, pdf.titleFont);
	top.setAlignment('center');
	top.setSpacingAfter(30);
	pdf.doc.add(top);
	var img = pdf.Image.getInstance('hat.gif');
	img.setAlignment(pdf.Image.MIDDLE);
	pdf.doc.add(img);
	var notice = new pdf.Paragraph("Documentation generated automatically from source on " 
				+ (new Date()).toUTCString(), pdf.bodyFont)
	notice.setSpacingBefore(30);
	pdf.doc.add(notice);
	pdf.doc.newPage();
}
