//not tested yet.
//to use, add crfTecant/crfData.js to requiresScript and in the call-back, run init
//will work with crfSetup as setup object

var crfData={};

crfData.init=
function(cb=null){
   this.print('[crfData:init]');
   let that=this;
   let action=function(){that.afterScripts(cb);};
   LABKEY.requiresScript(["crfTecant/runQuery.js","crfTecant/variableList.js"],action);
}

crfData.afterScripts=
function(cb=null){
   if (cb) cb();
}

crfData.setSetup=
function(setup){
   this.setup=setup;
}

crfData.getContainer=
function(label){
   return this.setup.getContainer(label);
}

crfData.print=
function(msg){
   console.log(msg);
}

//getters
crfData.getSnapshotObject=
function(){
   if (!("dataQueriesSnapshot" in this))
      this.dataQueriesSnapshot=new Object();
   return this.dataQueriesSnapshot;
}


crfData.getQuerySnapshot=
function(queryName){
   //check whether queryName is in snapshotObject?
   return this.getSnapshotObject()[queryName];
}

crfData.getLayoutObject=
function(){
   if (!("dataQueriesLayout" in this))
      this.dataQueriesLayout=new Object();
   return this.dataQueriesLayout;
}

crfData.getQueryLayout=
function(queryName){
   //check whether queryName is in snapshotObject?
   return this.getLayoutObject()[queryName];
}

crfData.getLookupObject=
function(){
   if (!("lookup" in this))
      this.lookup=new Object();
   return this.lookup;
}

crfData.getLookup=
function(queryName){
   let x=this.getLookupObject();
   if (queryName in x) return x[queryName];
   return null;
}

crfData.getQueryList=
function(){
   if (!("queryList" in this))
      this.queryList=new Object();
   return this.queryList;
}

crfData.getRegistration=
function(){
   let regQueryPars=variableList.parseVariables(this.setup.getSettings('registrationQuery'));
   let query=regQueryPars['query'];
   return this.getQuerySnapshot(query).rows;
}

crfData.getRegistrationMap=
function(value=null){
   let rows=this.getRegistration();
   let qMap=new Object();
   let key='Key';
   if (!value) value='participantStudyId';
   for (let i=0;i<rows.length;i++){
      qMap[rows[i][key]]=rows[i][value];
   }
   return qMap;
}

crfData.setDataLayout=
function(formId,cb){
   let fName='[setDataLayout]';
   this.print(fName);
	let rowsSetup=this.setup.selectFormSetupRows(formId);
   let queryArray=new Array();
	let dS=this.getLayoutObject();//reference only
   let qList=this.getQueryList();
	let qMap=this.setup.getMap('inputLists');
	//config.formConfig.lookup=new Object();
	for (let i=0;i<rowsSetup.length;i++){
		let entry=rowsSetup[i];
		//skip review rows
		if (entry['showFlag']=='REVIEW')
			continue;
		let queryId=entry['queryName'];
		let q=qMap[queryId];
		queryArray.push(runQuery.makeQuery(dS,'data',q,q,[]));
      qList[q]=0;
      this.print(fName+' adding '+q);
		if (entry['showQuery']!="NONE"){
			let sq=entry['showQuery'];
		   queryArray.push(runQuery.makeQuery(dS,'data',sq,sq,[]));
         qList[sq]=0;
         this.print(fName+' adding '+sq);
			
		}
	}

	//always add reviews
   let q='reviewComments';
   queryArray.push(runQuery.makeQuery(dS,'data',q,q,[]));
   qList[q]=0;
   let that=this;
   let action=function(){that.processLayout(cb);};
   runQuery.getDataFromQueries(this,queryArray,action);
}

//this happens after the for loop, so all dataQueries objects are set
crfData.processLayout=
function(cb=null){
   let fName='[processLayout]';
   let qList=this.getQueryList();
   //for layouts
   let queryArray=new Array();
   let targetObject=this.getLookupObject();
   let lookupSet=new Object();
   for (let q in qList){
      let qobject=this.getQueryLayout(q);
	   this.print(fName+" inspecting layout for "+q+" "+qobject);
	   qobject.fields=qobject.metaData.fields;
	   qobject.title=this.findTitle(q);

      //check for lookups
	   for (let f in qobject.fields){
		   //anything else is simple but lookup
		   let field=qobject.fields[f];
		   if (!("lookup" in field)) continue;
         let lookup=field.lookup;
         let qObject=this.getLookup(lookup.queryName);
         if (qObject) continue;
         //add to list
         let qName=lookup.queryName;
         let qCode=qName+':'+lookup.keyColumn+':'+lookup.displayColumn;
         let e=runQuery.makeQuery(targetObject,'data',qName,qCode,[]);
         //adjust minor settings
         if (lookup.containerPath) e.containerPath=lookup.containerPath;
         e.schemaName=lookup.schemaName;
         e.columns=lookup.keyColumn+','+lookup.displayColumn;
         lookupSet[qCode]=e;
         this.print(fName+' inserting '+qCode);
      }
   }
   for (let x in lookupSet){
      queryArray.push(lookupSet[x]);
      this.print(fName+' adding '+x);
      for (let v in lookupSet[x]){
         this.print(fName+' value ['+v+'] '+lookupSet[x][v]);
      }
   }
   //this.print(fName+' print '+targetObject.print);
   let that=this;
   let action=function(){that.processLookup(cb);};
   this.print(fName+' getDataFromQueries');
   runQuery.getDataFromQueries(this,queryArray,action);
   this.print(fName+' getDataFromQueries done');
}

crfData.processLookup=
function(cb=null){
   let fName="[processLookup]";

   let obj=this.getLookupObject();
   for (let q in obj){
	   this.print(fName+" "+q);
      let a=q.split(':');
      if (a.length<3) continue;
      let lookupName=a[0];
      let key=a[1];
      let val=a[2];
      obj[lookupName]=new Object();
      this.print(fName+' adding ['+lookupName+'] '+key+'/'+val);
      let lObject=obj[lookupName];

	   lObject.LUT=new Array();//key to value
	   lObject.ValToKey=new Array();//value to key
	   lObject.keyColumn=key
	   lObject.displayColumn=val;
      
      let qRows=obj[q].rows;
	   for (let i=0;i<qRows.length;i++){
         let r=qRows[i];
         this.print(fName+' LUT ['+r[key]+'] '+r[val]);
		   lObject.LUT[r[key]]=r[val];
		   lObject.ValToKey[r[val]]=r[key];
	   }
   }
	if (cb) cb();
}

crfData.setData=
function(crfRef,cb=null){
	fName='[setData]';
	//let crfMatch=this.getCRFref();
	//let parentCrf=config.formConfig.crfEntry['parentCrf'];
	//if (parentCrf!=undefined) crfMatch=parentCrf;

	this.print(fName+' form crf ['+crfRef+'] ');

   let queryArray=new Array();
   let targetObject=this.getSnapshotObject();
	//collect data and execute callback cb for queries in cb.queryList
   let qList=this.setup.getQueryList();
	for (q in qList){

		let filters=[LABKEY.Filter.create("crfRef",crfRef)];
      queryArray.push(runQuery.makeQuery(targetObject,'data',q,q,filters));

	}
   runQuery.getDataFromQueries(this,queryArray,cb);
}

crfData.setRegistration=
function(cb=null){
   let regQueryPars=variableList.parseVariables(this.setup.getSettings('registrationQuery'));
   let q=regQueryPars['query'];
   let queryArray=new Array();   
   let targetObject=this.getSnapshotObject();
   queryArray.push(runQuery.makeQuery(targetObject,'data',q,q,[]));
   runQuery.getDataFromQueries(this,queryArray,cb);
}