
var db        = require('../../lib/db');
var exec      = require('child_process').exec;
var fs        = require('fs');
var path      = require('path');
var printer   = require('printer');
var q         = require('q');
var http			= require('http');
var nsReport  = require('../../lib/nsreport');
var report    = new nsReport();

var jobInterval = 100;

var updateStatus = function(id, status) {
	db.run("UPDATE print_job SET status=$status WHERE id=$id", {$id:id, $status:status});
}

var processPdf = function(row) {
	updateStatus(row.id, 'PROCESSING');
  var pdfFile = row.report + '_'+ row.uuid + '.pdf';
  var pdfFullPath = path.normalize(__dirname + '/../../output/reports/' + pdfFile);

  var data = JSON.parse(row.param);
  if (typeof data.length!='number') {
  	data = [data];
  }

  var doc = report.createDocument(require('../../reports/' + row.report + '.js'), data);
  var stream = fs.createWriteStream(pdfFullPath);

  doc.pipe(stream);
  doc.end();

  stream.on('finish', function() {
  	console.log('GEN PDF DONE');

		updateStatus(row.id, 'PRINTING');

		var cmd = '"' + path.normalize(__dirname + '/../../bin/SumatraPDF.exe') + '"'
	    + ' -print-to "' + row.printer + '" -silent -exit-when-done '
	    + '"' + pdfFullPath + '"';

		console.log('cmd2=', cmd);
		var child = exec(cmd, function(err, stdout, stderr) {
			if(err) {
				console.log('ERROR');
				updateStatus(row.id, 'ERROR');
				return;
			}
			console.log('DONE');
			updateStatus(row.id, 'DONE');
		});
  });
}

var processPdfUrl = function(row) {
	updateStatus(row.id, 'PROCESSING');
	var data = JSON.parse(row.param);
	if (!data || !data.url){
		console.log('ERROR1');
		updateStatus(row.id, 'ERROR');
		return;
	}
	var tmp = data.url.split('/');
	if (tmp.length==1) {
		console.log('ERROR2');
		updateStatus(row.id, 'ERROR');
		return;
	}

	var request = http.get(data.url, function(response) {
		var fname = tmp[tmp.length-1];
		var filename = path.normalize(__dirname + '/../../output/printers/' + fname);
		var file = fs.createWriteStream(filename);
	  file.on('finish', function() {
			updateStatus(row.id, 'PRINTING');

			var cmd = '"' + path.normalize(__dirname + '/../../bin/SumatraPDF.exe') + '"'
		    + ' -print-to "' + row.printer + '" -silent -exit-when-done '
		    + '"' + filename + '"';

			console.log('cmd2=', cmd);
			var child = exec(cmd, function(err, stdout, stderr) {
				if(err) {
					console.log('ERROR');
					updateStatus(row.id, 'ERROR');
					return;
				}
				console.log('DONE');
				updateStatus(row.id, 'DONE');
			});
		});
		response.pipe(file);
	});
	request.on('error', function() {
		console.log('ERROR');
		updateStatus(row.id, 'ERROR');
	});
};

var processEsc = function(row) {
	updateStatus(row.id, 'PROCESSING');

	if (typeof row.param === 'string') {
		row.param = JSON.parse(row.param);
	}

	fs.readFile(__dirname + '/../../reports/' + row.report + '.json', 'utf8', function(err, data) {
		if (err) {
			console.log(err);
			updateStatus(row.id, 'ERROR');
			return;
		}
		var reportOpt = JSON.parse(data);

		var v_unit = 180, // 1/180 in
			h_unit = 360,
			margin_top = 0.45, // 0.375in
			pageWidth = 8.5, // 8.5in
			ESC = 27,
			CR = 13,
			LF = 10,
			FF = 12,
			cmd = [];
		///////////////////////////////////////////
		// 1. reset by ESC @
		// 2. unit of line spacing
		// 3. set printing area
		// foreach print item
		//   4. select font
		//   5. select supporting features
		//   6. set print position
		//   7. send one line print data
		//   8. send CR LF
		// 9. send FF
		// 10. end printing by ESC @

		// 1. ESC @
		[].push.apply(cmd, [ESC,'@'.charCodeAt(0)]);
		[].push.apply(cmd, [ESC,'('.charCodeAt(0),'t'.charCodeAt(0),3,0,1,19,0]); // load TIS11 charmap
//		[].push.apply(cmd, [ESC,'0'.charCodeAt(0)]); // 1/8 line height
//		[].push.apply(cmd, [ESC,'C'.charCodeAt(0),44]); // 44 * 1/8 = 5.5in
		[].push.apply(cmd, [ESC,'('.charCodeAt(0),'U'.charCodeAt(0),1,0,10]);// 360dpi
//		[].push.apply(cmd, [ESC,'('.charCodeAt(0),'C'.charCodeAt(0),2,0,120,15]);
		[].push.apply(cmd, [ESC,'('.charCodeAt(0),'C'.charCodeAt(0),2,0,188,7]); // 1980ppi
		[].push.apply(cmd, [ESC,'M'.charCodeAt(0)]); // P=10cpi, M=12cpi, g=15cpi
		[].push.apply(cmd, [ESC,'l'.charCodeAt(0),0]); // left 0in
//		[].push.apply(cmd, [ESC,'Q'.charCodeAt(0),204]); // right 102 * 1/12 = 8.5in
	//	[].push.apply(cmd, [ESC,'!'.charCodeAt(0), 0 + 32]); // 12cpi + double width
		[].push.apply(cmd, [ESC,'k'.charCodeAt(0),1]); // 0 roman, 1 sans serif
		//[].push.apply(cmd, [ESC,'W'.charCodeAt(0),1]); // double width font
		[].push.apply(cmd, [ESC,'t'.charCodeAt(0),1]); //select table 1
		/*
		//
		// 2.1 ESC P  === 10cpi
		reportOpt.cpi = reportOpt.cpi || 10;
		if (reportOpt.cpi==10) {
			cmd.push(ESC);cmd.push('P'.charCodeAt(0)); // 10cpi
		}
		// 2.2 ESC 0 === 1/8 inch line spacing
		cmd.push(ESC);cmd.push('0'.charCodeAt(0));
		cmd.push(ESC);cmd.push('C'.charCodeAt(0));cmd.push(44); // 48*1/8 = 5.5in
		// 3. set print area
		reportOpt.leftMargin = reportOpt.leftMargin || 0.5;
		cmd.push(ESC);cmd.push('l'.charCodeAt(0));cmd.push(Math.floor(reportOpt.leftMargin*reportOpt.cpi)); // 5char/10cpi == 0.5in
		reportOpt.rightMargin = reportOpt.rightMargin || 0.5;
		cmd.push(ESC);cmd.push('Q'.charCodeAt(0));cmd.push(Math.floor((8.5-reportOpt.rightMargin)*reportOpt.cpi)); // 80char/10cpi == 8.0in from left
		//
		*/
//		console.log('reportOpt', reportOpt);
		var escItem = [];
		for(var i in reportOpt.items) {
			var item = reportOpt.items[i];
			if (typeof row.param[i] === 'undefined'
				|| row.param[i]==='') {
				continue;
			}
			var x = Math.floor(item.x*h_unit);
			var y = Math.floor((item.y-margin_top)*v_unit);
			var arr = toEscArray(row.param[i]);
			escItem.push({x:x,y:y,data:arr[0]});
			if (arr[1].length > 0) {
				escItem.push({x:x,y:y-16,data:arr[1]});
			}
			if (arr[2].length > 0) {
				escItem.push({x:x,y:y+20,data:arr[2]});
			}
		}
		//console.log('before sort', escItem);
		// sorting escItem
		escItem.sort(function(a,b) {
			if (a.y < b.y) {
				return -1;
			}
			if (a.y > b.y) {
				return 1;
			}
			if (a.x < b.x) {
				return -1;
			}
			if (a.x > b.x) {
				return 1;
			}
			return 0;
		});
		//console.log('after sort', escItem);
		var cur_y = 0;
		for(var i in escItem) {
			var item = escItem[i];
			// feed y
			if (item.y > cur_y) {
				cmd.push(CR);
				var delta_y = (item.y-cur_y);
				while (delta_y > 0) {
					if (delta_y > 255) {
						cmd.push(ESC);cmd.push('J'.charCodeAt(0));cmd.push(255);
						delta_y -= 255;
					} else {
						cmd.push(ESC);cmd.push('J'.charCodeAt(0));cmd.push(delta_y);
						delta_y = 0;
					}
				}
				cur_y = item.y;
			}
			// move x
			var delta_x = item.x;
			cmd.push(ESC);cmd.push('$'.charCodeAt(0));cmd.push(item.x%256);cmd.push(Math.floor(item.x/256));
			[].push.apply(cmd, item.data);
		}
		cmd.push(FF);
//		cmd.push(ESC);cmd.push('@'.charCodeAt(0));

    updateStatus(row.id, 'PRINTING');

    printer.printDirect({
  		data:new Uint8Array(cmd), // or simple String: "some text"
  		printer:row.printer, // printer name
  		type:'RAW', // type: RAW, TEXT, PDF, JPEG, .. depends on platform
  		success:function(jobID){
  			console.log("sent to printer with ID: "+jobID);
  			updateStatus(row.id, 'DONE');
  		},
  		error:function(err){
  			console.log(err);
  			updateStatus(row.id, 'ERROR');
  		},
  	});
	});
}

var run = function() {
	db.get("SELECT * FROM print_job WHERE status='PENDING'", function(err, row) {
    if (typeof row==='undefined') {
      setTimeout(run, jobInterval);
      return;
    }

		console.log('FOUND JOB:', row.id, ',', row.format);

    if (row.format=='PDF') {
			processPdf(row);
		} else if (row.format == 'ESC') {
			processEsc(row);
		} else if (row.format == 'PDFURL') {
			console.log('PDFURL');
			processPdfUrl(row);
		}

    setTimeout(run, jobInterval);
	});
};

var toEscArray = function(s) {
	var len = s.length,
		base = [],
		top = [],
		bottom = []
		;
	var addTop = function(ch) {
		for(var i = top.length; i < base.length-1;i++) {
			top.push(32);
		}
		top.push(ch);
	}
	var addBottom = function(ch) {
		for (var i = bottom.length; i < base.length-1; i++) {
			bottom.push(32);
		}
		bottom.push(ch);
	}
	for (var i=0; i < len; i++) {
		var ch = s.charCodeAt(i);
		var next = i < len-1 ? s.charCodeAt(i+1) : 0;
		if (ch < 128) {
			base.push(ch);
		}
		// thai
		if (ch >= 0xe01 && ch <= 0xe5b) {
			if (ch >= 0xe38 && ch <= 0xe3a) { // สระล่าง
				addBottom(ch - 0xe01 + 161);
			} else if (ch == 0xe31) { // ไม้หันอากาศ
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4b) {
					addTop(128 + next-0xe48);
					i++;
				} else {
					addTop(ch - 0xe01 + 161);
				}
			} else if (ch == 0xe34) { // สระอิ
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4c) {
					addTop(132 + next-0xe48);
					i++;
				} else {
					addTop(ch - 0xe01 + 161);
				}
			} else if (ch == 0xe35) { // สระอี
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4b) {
					addTop(137 + next-0xe48);
					i++;
				} else {
					addTop(ch - 0xe01 + 161);
				}
			} else if (ch == 0xe36) { // สระอึ
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4b) {
					addTop(141 + next-0xe48);
					i++;
				} else {
					addTop(ch - 0xe01 + 161);
				}
			} else if (ch == 0xe37) { // สระอือ
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4b) {
					addTop(145 + next-0xe48);
					i++;
				} else {
					addTop(ch - 0xe01 + 161);
				}
			} else if (ch == 0xe33) { // สระอำ
				if (i < len - 1 && next >= 0xe48 && next <= 0xe4b) {
					addTop(149 + next-0xe48);
					i++;
				} else {
					addTop(0xe4d - 0xe01 + 161);
				}
				base.push(0xe32 - 0xe01 + 161);
			} else if (ch >= 0xe42 && ch <= 0xe44) { // สระโอ ไม้มลาย ไม้ม้วน
				base.push(160);
				addTop(ch-0xe42+252);
			} else if (ch >= 0xe47 && ch <= 0xe4e) { // สระบน
				if (ch != 0xe47 && i < len - 1 && next == 0xe33) { // ถัดไปเป็นสระอำ
					addTop(149 + ch-0xe48);
					base.push(0xe32-0xe01+161);
					i++;
				} else {
					addTop(ch-0xe01+161);
				}
			} else {
				base.push(ch - 0xe01 + 161);
			}
		}
	}
	return [base,top,bottom];
}


exports.run = run;
