//@ts-check
var ibmdb = require("ibm_db")

/**
 * 
 * @param {ibmdb.Database} connection 
 * @param {string} query 
 * @returns 
 */
function queryAsync(connection, query){
	return new Promise(function(resolve,reject){
		connection.query(query,function (err, rows, sqlca){
			//console.log(err, rows, sqlca)
			if(err){
				//console.log(err.message)
				reject(err)
			}else{
				resolve({
					rows: rows,
					state: sqlca
				})
			}
		});
	})
}


/**
 * 
 * @param {ibmdb.Database} connection 
 * @param {string} tableNameFull 
 * @param {number} maxRows 
 * @returns 
 */
async function readTable(connection, tableNameFull, maxRows){
	//var rows = await queryAsync("select * from " + tableName)
	var tableName = tableNameFull.split(".")[1]
	var result = await queryAsync(connection, "Select distinct(name), ColType, Length from Sysibm.syscolumns where tbname = '" + tableName + "';")
	//console.log(result.rows)
	var timestampColumn = ""
	var columns = []
	for(var y in result.rows){
		var colName = result.rows[y].NAME 
		if(colName.indexOf("TIMESTAMP")!= -1){
			timestampColumn = colName
		}
		columns.push(colName + "(" + result.rows[y].COLTYPE.trim() + ") ")
	}
	result = await queryAsync(connection, "Select * from " + tableNameFull + (timestampColumn ? " ORDER BY " + timestampColumn + " DESC" : "") + " FETCH FIRST " + maxRows + " ROWS ONLY;")
	
	return result.rows
}

module.exports = class EosM290{
	connected = false
	constructor(options){
		var connectionString = ""
		
		if(!options.host){
			throw new Error("option host is not defined")
		}
		if(!options.user){
			console.error("option user is not defined")
		}
		if(!options.pass){
			console.error("option pass is not defined")
		}
		connectionString += "DATABASE=" + (options.databaseName || "LOGDB") + ";"
		connectionString += "HOSTNAME=" + options.host + ";"
		connectionString += "PORT=" + (options.port || 49999) + ";"
		connectionString += "PROTOCOL=TCPIP;"
		connectionString += "UID=" + options.user + ";"
		connectionString += "PWD=" + options.pass + ""
		this.connectionString = connectionString
		try{
			/**@type {ibmdb.Database} */
			this.connection = ibmdb.openSync(this.connectionString)
			this.connected = true
		}catch(err){
			console.error(err)
			console.error("Could not connect to IBM2DB at " + options.host)
			this.connected = false
		}
		
		// override type to match others
		this.type = "3d-printer"
	}
	
	async getDeviceInfo(){
		var out = {}
		out.title = "EOS Printer"
		//console.log(this.connection)
		if(!this.connected || !this.connection || !this.connection.connected){
			try{
				if(this.connection){
					try{
						this.connection.close(function(){})
					}catch(e){}
				}
				this.connection = ibmdb.openSync(this.connectionString, {connectTimeout: 1})
				this.connected = true
			}catch(err){
				out.status = "Disconnected"
				out.values_overview = {}
				out.values_overview.status = {
					type: "value",
					title:"Status",
					value: "Disconnected",
				}
				return [out]
			}
		}
		
		try{
			// title
			
			var machineNames = await readTable(this.connection, "EOSLOG.MACHTYPES_TBL",20)
			for(var x in machineNames){
				var machineName = machineNames[x].MT_TYPE
				if(machineName && machineName.indexOf("type") == -1){
					out.title = "EOS " + machineName
					break
				}
			}
			
			// status
			var statuses = await readTable(this.connection, "EOSLOG.STATUS_TBL",20)
			for(var x in statuses){
				var statusText = statuses[x].SE_TEXTDATA || ""
				if(statusText.indexOf("<MachineStatus>") == 0){
					var jobStatusStart = statusText.indexOf("<LastStatus>") + 12
					var jobStatusEnd = statusText.indexOf("</LastStatus>",jobStatusStart)
					if(jobStatusStart != -1 && jobStatusEnd != -1){
						out.status = statusText.substring(jobStatusStart, jobStatusEnd)
					}
				}
			}
			
			out.values = {}
			out.values_overview = {}
			
			if(out.status){
				out.values_overview.status = {
					type:"value",
					title:"Status",
					value: out.status,
				}
			}
		}catch(err){
			if(err.message && err.message.indexOf("connection") != -1){
				this.connected = false
				return []
			}else{
				throw err
			}
		}
		
		return [out]
	}
}