/**  factandterms.js
 contains the code to control popover selective display by using javascript: pseudo protocol. It loads PacioliModel.json file first (and once)
 and changes all the target attributes on selected anchors to "_self" to be able to execute those functions as defined in this file. 
 Finally, it assigns a function as content to each popover to dinamically defined whether to call another web page or to open a popover. 
 */ 

/* factandterms.js 
   Popover initialization and control, including popovers to explain facts and terms. 
*/ 

/* factandterms.js
    it includes the pako zlib library and it is intended to be browserified into factandterms.js
*/
//const pako = require('pako'); // http://nodeca.github.io/pako/

var json_pacioli = {}; // Global variable for the PacioliModel.js if it is loaded. 

this.onload = function(){

	var baseURL = document.URL;

	prepareAnchors(); 
	
	if(isHttpLink(baseURL)) {
        if(isNotIpfsLink(baseURL)) {
            console.log("Don't need PacioliModel.js.gzip"); 
        } else {
            // serverless operation with popovers from the same IPFS url
            // Load from IPFS

			fetch('PacioliModel.js.gzip').then(res => {
						//console.log('res', res);
						return res.arrayBuffer(); 
					}) // Download gzipped tar file and get ArrayBuffer
                    //.then(pako.inflate)             // Decompress gzip using pako
					.then(function(file_content) {
						console.log('PacioliModel.js.gzip loaded ---');
						// 	console.log('pako', pako);
						// 	//console.log('window', window);
						//console.log(JSON.stringify(file_content));
						//     console.log('PacioliModel.js ---');
						const unzipped = pako.inflate(file_content, {to: "string"});
						//     console.log(JSON.stringify(unzipped));
						//console.log('unzipped ---', unzipped); 
						json_pacioli = JSON.parse(unzipped.replace("var pacioliModel =", ''));
						//console.log('json_pacioli', json_pacioli); 
					});

            // wait a second
            setTimeout(function() {
                //console.log('After loading the page, json_pacioli ='+JSON.stringify(json_pacioli)); 
            }, 1000); 
        }
	} else {
        console.log('PacioliModel.js.gzip can not be loaded from the local file:// system');

	}
}

// we must prepare anchors in any case
function prepareAnchors() {
	// preparing all anchors and popovers links on each page (tables are dealt with at the prolog layer)
	var els = document.querySelectorAll("a[href^='javascript:']"); 
	var ela = document.querySelectorAll("a"); 
	//var elg = document.querySelectorAll("a[*|xlink]"); 
	var elg = document.querySelectorAll('a[*|href]') // all xlink:href 

	//console.log("there are "+ela.length+" links"); 
	//console.log("there are "+els.length+" links with href^='javascript:factDetail'] or termDetail"); 
	//console.log("there are "+elg.length+" xlinks "); 	
	
	// set a unique id for all the anchors in the page (does not include all anchors in tables. Only first page)
	for (var i = 0, l = els.length; i < l; i++) {
		var el = els[i];
		var previous = el.getAttribute("id"); 
		if (previous) {
			//console.log("Keeping "+el.id+" as id of "+el)
		} else {
			el.setAttribute("id", "a"+i); 
			//console.log("Setting "+el.id+" as id of "+el); 
		}
	}

	// set javascript: anchors as popovers with dismissible behaviour
	for (var i = 0, l = els.length; i < l; i++) {
		  var el = els[i];
		  el.target = "_self";						// we need this as popovers launch js in this page
		  el.setAttribute("data-toggle", "popover"); 	// activate content function (see below)
		  el.setAttribute("data-trigger", "focus"); 	// dismissible behaviour
		  //console.log("Fixing attributes of "+el.id); 
	}

	// set a unique id for all the xlink anchors (graphs) in the page, if any
	for (var i = 0, l = elg.length; i < l; i++) {
		var el = elg[i];
		var previous = el.getAttribute("id"); 
		if (previous) {
			//console.log("Keeping "+el.id+" as id of "+JSON.stringify(el))
		} else {
			el.setAttribute("id", "ag"+i); 
			//console.log("Setting "+el.id+" as id of "+JSON.stringify(el)); 
		}
	}

	// set javascript: anchors as popovers with dismissible behaviour for the xlink anchors (graphs)
	for (var i = 0, l = elg.length; i < l; i++) {
		  var el = elg[i];
		  el.target = "_self";						// we need this as popovers launch js in this page
		  el.setAttribute("data-toggle", "popover"); 	// activate content function (see below)
		  el.setAttribute("data-trigger", "focus"); 	// dismissible behaviour
		  //console.log("Fixing attributes of "+el.id); 
	}

}

function isNotJavascriptLink(URL) {
	return (URL.indexOf("javascript:factDetail(")<0)&&(URL.indexOf("javascript:termDetail(")<0); 
}

function isJavascriptTermLink(URL) {
	return (URL.indexOf("javascript:termDetail(")>-1); 
}

function isHttpLink(URL) {
	return (URL.indexOf("http")>-1)&&(URL.indexOf("http")<4); 	//>-1 and <4 -> http:// server involved 
}

function isNotIpfsLink(URL) {
	return (URL.indexOf("ipfs")<0); 
}

function factDetail(RelURL) { 
	//console.log("javascript:factDetail("+RelURL+") clicked");

	var el = document.activeElement;  // get THIS anchor
	var baseURL = document.URL; 	  // get the hosting document
	
	//console.log(baseURL);
	RelURL = decodeURIComponent(RelURL); 									// decodeURI
	
	// it is NOT an IPFS link
	if(isNotIpfsLink(baseURL)&&isHttpLink(baseURL)) { 							// not on ipfs but http
		//RelURL = encodeURIComponent(RelURL); 
		//console.log("Opening (in other window):"+baseURL+RelURL); 
		RelURL = RelURL.split("+").join("%2B");
		//console.log("Comparing"+RelURL); 
		window.open(RelURL, "_blank");
	// it is an ipfs: popover has to be filled in
	} else { 																	// on ipfs or disconnected 
		//console.log(el.attributes.href.nodeValue); 
		//console.log(el.attributes.id.nodeValue); 
		//console.log("Relative URL is being trimmed to |"+RelURL+"|"); 

		if(el.attributes.id) { // if the id attrib is available, popover is possible
			//var selector = "a[href='"+el.attributes.href.nodeValue+"']";
			var selector = "a[id='"+el.attributes.id.nodeValue+"']"; 
			//console.log("Content selector: "); console.log($(selector)); 

			// prepare content of the popover
			$(selector).popover( {html:true,  content: function() {
				var info = $(this).data('content'); // if previous static content exists
				//var info = ""; 

				var key = extractKey(RelURL); 
				if($.isEmptyObject(key)) {			// empty key!
					//console.log("no info available for "+RelURL); 
				} else {					// key functional
					//console.log("working off line with key :"+JSON.stringify(key)); 
					var detail = filterData(key, json_pacioli); 
					//info = "<p>Fact Details:</p><p>"+JSON.stringify(detail)"</p>";
					info =  builtReport(json_pacioli, detail, "fact"); 
				}
				return info

			} 	} 	); 
		
			$(selector).popover('toggle')
		
			$(selector).on('show.bs.popover', function () {		
				  //console.log("Popover for "+RelURL+" being shown "); 
			})

		} else { // try a separate web page for the reporting
			// try the web page for the reporting
			// https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createHTMLDocument

			var info = ""; 

			var key = extractKey(RelURL); 
			if($.isEmptyObject(key)) {			// empty key!
				//console.log("no info available for "+RelURL); 
			} else {					// key functional
				//console.log("working off line and without popovers with key :"+JSON.stringify(key)); 
				var detail = filterData(key, json_pacioli); 
				info = "<p>Fact Details:</p><p>"+builtReport(json_pacioli, detail, "fact")+"</p>";
				//info =  builtReport(json_pacioli, detail, "fact"); 
			}

  			//let doc = document.implementation.createHTMLDocument("Term Details");
			p = document.getElementById('FactDetails'); 
			if (p) {
				let newp =  document.createElement("p");
				newp.id = 'FactDetails';
				newp.innerHTML = info;  			
				try {
					document.body.replaceChild(newp, p);
				  } catch(e) {
					//console.log(e);
				  }

			} else {
				let p = document.createElement("p");
				p.id = 'FactDetails';
				p.innerHTML = info;  			
				try {
					document.body.appendChild(p);
				  } catch(e) {
					//console.log(e);
				  }
			}
			document.getElementById('FactDetails').scrollIntoView()

		}

	}
	 
	//console.log("javascript:factDetail(\""+RelURL+"\") finished");

}

function termDetail(RelURL) {	
	var el = document.activeElement;  // get THIS anchor
	var baseURL = document.URL; 	  // get the hosting document
	
	//console.log(baseURL); 
	RelURL = decodeURIComponent(RelURL); 									// decodeURI
	
	// it is NOT an IPFS link
	if(isNotIpfsLink(baseURL)&&isHttpLink(baseURL)) { 							// not on ipfs but http
		//RelURL = encodeURIComponent(RelURL); 
		//console.log("Opening (in other window):"+baseURL+RelURL); 
		RelURL = RelURL.split("+").join("%2B");
		//console.log("Comparing"+RelURL); 
		window.open(RelURL, "_blank");
	// it is an ipfs: popover has to be filled in
	} else { 																	// on ipfs or disconnected
		//console.log(el.attributes.href.nodeValue); 
		//console.log(el.attributes.id.nodeValue); 

		//console.log("Relative URL is being trimmed to |"+RelURL+"|"); 
		if(el.attributes.id) { // if the id attrib is available, popover is possible
			//var selector = "a[href='"+el.attributes.href.nodeValue+"']";
			var selector = "a[id='"+el.attributes.id.nodeValue+"']"; 
			//console.log("Content selector: "); console.log($(selector)); 

			// prepare content of the popover
			$(selector).popover( {html:true,  content: function() {
				var info = $(this).data('content'); // if previous static content exists
				//var info = ""; 

				var key = extractKey(RelURL); 
				if($.isEmptyObject(key)) {			// empty key!
					//console.log("no info available for "+RelURL); 
				} else {					// key functional
					//console.log("working off line with key :"+JSON.stringify(key)); 
					var detail = filterData(key, json_pacioli); 
					//info = "<p>Fact Details:</p><p>"+JSON.stringify(detail)"</p>";
					info =  builtReport(json_pacioli, detail, "term"); 
				}
				return info

			} 	} 	); 
		
			$(selector).popover('toggle')
		
			$(selector).on('show.bs.popover', function () {		
				  //console.log("Popover for "+RelURL+" being shown "); 
			})

		} else { 
			// try the web page for the reporting
			// https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createHTMLDocument

			var info = ""; 

			var key = extractKey(RelURL); 
			if($.isEmptyObject(key)) {			// empty key!
				//console.log("no info available for "+RelURL); 
			} else {					// key functional
				//console.log("working off line and without popovers with key :"+JSON.stringify(key)); 
				var detail = filterData(key, json_pacioli); 
				info = "<p>Term Details:</p><p>"+builtReport(json_pacioli, detail, "term")+"</p>";
				//info =  builtReport(json_pacioli, detail, "term"); 
			}

  			//let doc = document.implementation.createHTMLDocument("Term Details");
			p = document.getElementById('TermDetails'); 
			if (p) {
				let newp =  document.createElement("p");
				newp.id = 'TermDetails';
				newp.innerHTML = info;  			
				try {
					document.body.replaceChild(newp, p);
				  } catch(e) {
					//console.log(e);
				  }

			} else {
				let p = document.createElement("p");
				p.id = 'TermDetails';
				p.innerHTML = info;  			
				try {
					document.body.appendChild(p);
				  } catch(e) {
					//console.log(e);
				  }
			}
			document.getElementById('TermDetails').scrollIntoView()

		}

	}
	console.log("javascript:termDetail(\""+URL+"\") clicked")
}

// extractKey from 'fact?factkey=factKey(proof:'CurrentAssets','I-2020','U-Monetary-USD',reported)'
// or
// term?concept=fac:'LiabilitiesRollUp'
function extractKey(FK) {
	var result = {}; 
	
	console.log("Extracting key from |"+FK+"|"); 

	try {
		if(FK.indexOf("factKey(")>0) { // if it is a fact query
			// Procedure to extract key for facts:
			//var arg = FK.slice(FK.indexOf("("), FK.indexOf(")")+1);
			//var arg = FK.slice(FK.indexOf("factKey(")+8, FK.indexOf(")")+1); // adjusted to full fact?queries
			var arg = FK.slice(FK.indexOf("factKey(")+8, FK.length-1);
			var concept = arg.slice(0, arg.indexOf(",")); 
			//console.log("arguments |"+arg+"|");
			//   console.log("concept |"+concept+"|"); 

			var second_stage = arg.slice(arg.indexOf(","),arg.length);
			var context = second_stage.slice(1, second_stage.indexOf(",", 1));
			context = context.split("'").join(""); // cleaning border quotes to match data
			//console.log("second_stage |"+second_stage+"|");
			//console.log("context |"+context+"|"); 

			var third_stage = second_stage.slice(second_stage.indexOf(",", 1), second_stage.length);
			var unit = third_stage.slice(1, third_stage.indexOf(",", 1));
			unit = unit.split("'").join(""); // cleaning border quotes to match data
			//console.log("third_stage |"+third_stage+"|");
			//console.log("unit |"+unit+"|"); 

			var fourth_stage = third_stage.slice(third_stage.indexOf(",", 1), third_stage.length);
			//var origin = fourth_stage.slice(1, fourth_stage.indexOf(")"));
			var origin = fourth_stage.slice(1, fourth_stage.length);
			//console.log("fourth_stage |"+fourth_stage+"|");
			//console.log("origin |"+origin+"|"); 
    
    		result = { "concept": concept, "context": context, "unit": unit, "origin": origin};
    	} else { // it must be a term query
			var concept = FK.slice(FK.indexOf("concept=")+8, FK.length); // adjusted to term queries
			concept = concept.split("\"").join("");
   			//console.log("concept |"+concept+"|");     			
   			result = { "concept": concept};
    	}
	}
	catch (e) {
   		console.log(e); 
	}

	console.log("Key extracted:"+JSON.stringify(result)); 

	return result; 
}


// filterData of element key form json Model
function filterData(key, json) {

	var result; 

    if(key["context"]) { // it is a fact key
    	// get the data
    	const data = json.cached_fact.data; 

    	result = data.filter(el => 
        	//el[0] == "01-Balance Sheet"
       		(el[json.cached_fact.columns.indexOf("concept")] == key["concept"]) && 
        	(el[json.cached_fact.columns.indexOf("context")] == key["context"]) && 
        	//(el[json.cached_fact.columns.indexOf("unit")] == key["unit"]) && // failing key?
        	(el[json.cached_fact.columns.indexOf("rawUnit")] == key["unit"]) && // correct key
        	(el[json.cached_fact.columns.indexOf("origin")] == key["origin"])
    	);     
		//console.log("data of "+JSON.stringify(key)+" filtered from:"+JSON.stringify(data));
    } else {    
    	// get the data	
    	const data = json.concept.data; 

    	result = data.filter(el => 
       	(el[json.concept.columns.indexOf("name")] == key["concept"])
    	);    
		//console.log("data of "+JSON.stringify(key)+" filtered from:"+JSON.stringify(data)); 
    }

    return result; 

}

// built a report to be shown in the popover
function builtReport(json, entry, type) {
	report = "<table><ul>"; 

	//console.log("lenght of the record to display:>"+entry[0].length+"<\n"); 
	//console.log("element to display:>"+entry[0][1]+"<\n"); 
	if (entry.length === 0) { 
		//console.log("the report is empty!");
		report = report + "</ul><p>No information available</p></table>"; 
		return report; 
	}

	if(type=="fact") {	// report for facts
		//console.log("Report for facts"); 
		for (var i=0; i<entry[0].length; i++){
			if ((!(i==8))&&(!(i==9))&&(!(i==11))&&(!(i==17))) { // excluding columns 8,9,11,17 as examples
				//console.log( i, entry[0][i] );
				//report = report+"<tr><td><b>"+json.cached_fact.columns[i]+"</b>: </td><td>"+entry[0][i]+"</td></tr>";
				//report = report+" "+json.cached_fact.columns[i]+":"+entry[0][i]+" \n"; 
				report = report+"<li><b>"+json.cached_fact.columns[i]+"</b>:"+entry[0][i]+"</li>"; 
			} else {
				//console.log("excluded: "+entry[0][i]); 
			}
		}
	} else { // type = "term" -> term detail	
		//console.log("Report for terms"); 	
		for (var i=0; i<entry[0].length; i++){
			if ((!(i==8))&&(!(i==9))&&(!(i==11))&&(!(i==17))) { // excluding columns 8,9,11,17 as examples
				//console.log( i, entry[0][i] );
				report = report+"<li><b>"+json.concept.columns[i]+"</b>:"+entry[0][i]+"</li>"; 
			} else {
				//console.log("excluded: "+entry[0][i]); 
			}
		}
	}

	report = report + "</ul></table>"; 
	//console.log(report); 

	return report; 

}
