var formPortal={};

//global config variable
formPortal.config=new Object();

formPortal.setDebug=
function(debug=null){
   if (debug){
      this.print=function(msg){debug.print(msg);};
      this.clear=function(){debug.clear();}
      return;
   }
   //provide default functions if not debug object is available
   this.print=function(msg){console.log(msg);}
   this.clear=function(){;}
}


formPortal.setDebug();

formPortal.getMode=
function(){
	if ("role" in this.config){
		return this.config.role;
	}
	return "crfEditor";
}

formPortal.doNothing=
function(){
	this.print('doNothing called');
}

//load runQuery.js

formPortal.printMessage=
function(msg){
	let txt=this.config.document.createElement("p");
	this.config.document.getElementById(this.config.div).appendChild(txt);
	txt.innerText=msg;
}


formPortal.userName=
function(id){
	let formConfig=this.config.formConfig;
	for (let i=0;i<formConfig.users.rows.length;i++){
		if (formConfig.users.rows[i].UserId!=id)
			continue;
		return formConfig.users.rows[i].DisplayName;
	}
	return "NONE";
}

formPortal.setContainer=
function(label,container){
   let config=this.config;
	if (!(config.formConfig.hasOwnProperty('container'))){
		config.formConfig.container=new Array();
	}
	config.formConfig.container[label]=container;
}


formPortal.getContainer=
function(label){
	return this.config.formConfig.container[label];
}

formPortal.init=
function(cb=null){
   let that=this;
   let action=function(){that.scriptsLoaded(cb);};
   LABKEY.Utils.requiresScript(["crfTecant/runQuery.js","crfTecant/formGenerator.js","crfTecant/variableList.js"],action);
}

formPortal.scriptsLoaded=
function(cb=null){
   formGenerator.set(this);
   if (cb) cb();
}

formPortal.generateFormArray=
function(){
   let that=this;
   let action=function(){that.fcontinue0();};
   this.init(action);
}

formPortal.fcontinue0=
function(){
	this.print("generateFormArray "+this.getMode());
   let config=this.config;
	
	config.formConfig=new Object();
	config.formConfig.softwareVersion='T.2.01';	//report software version
	//report software version
	config.document.getElementById('version').innerText=config.formConfig.softwareVersion;	
	
	this.setContainer('data',LABKEY.ActionURL.getContainer());
	this.setContainer('config',LABKEY.ActionURL.getContainer());
	this.setContainer('CRF',LABKEY.ActionURL.getContainer());

	let selectRows=new Object();
	//this is local data
	selectRows.containerPath=this.getContainer('CRF');
	selectRows.schemaName='lists';
	selectRows.queryName='crfSettings';
	//store form related data to this object
   let that=this;
	selectRows.success=function(data){that.afterSettings(data);};
	LABKEY.Query.selectRows(selectRows);

}

formPortal.afterSettings=
function(data){
   let fName="[afterSettings]";
   let config=this.config;
	config.formConfig.settings=new Array();
	for (let i=0;i<data.rows.length;i++){
		let n=data.rows[i]['name'];
		let v=data.rows[i]['value'];
		config.formConfig.settings[n]=v;
	}

	let st=config.formConfig.settings;
	this.print(fName);
	for (let k in st){
		this.print(fName+'\t'+k+'='+st[k]);
	}

	//if ('dataContainer' in st){
	//	setContainer('data',st['dataContainer']);
	//}
	let vname='configContainer';
	if (vname in st){
		this.setContainer('config',st[vname]);
	}
	this.print(fName+' config: '+this.getContainer('config'));
	this.print(fName+' data: '+this.getContainer('data'));


	//setup queryArray
	let queryArray=new Array();

   //targetObject
   let targetObject=config.formConfig;

   //static variables
	queryArray.push(runQuery.makeQuery(targetObject,'data','crfStaticVariables','crfStaticVariables',[]));
	//Forms
	queryArray.push(runQuery.makeQuery(targetObject,'config','Forms','dataForms',[]));
	//users
	queryArray.push(runQuery.makeQuery(targetObject,'data','users','users',[]));
	queryArray[queryArray.length-1].schemaName='core';
	//inputLists
	queryArray.push(runQuery.makeQuery(targetObject,'config','inputLists','inputLists',[]));
	//crfEditors
	queryArray.push(runQuery.makeQuery(targetObject,'config','crfEditors','crfEditors',[]));
	//crfMonitors
	queryArray.push(runQuery.makeQuery(targetObject,'config','crfMonitors','crfMonitors',[]));
	//crfSponsors
	queryArray.push(runQuery.makeQuery(targetObject,'config','crfSponsors','crfSponsors',[]));
	//crfManagers
	queryArray.push(runQuery.makeQuery(targetObject,'config','crfManagers','crfManagers',[]));
	//FormStatus
	queryArray.push(runQuery.makeQuery(targetObject,'config','FormStatus','formStatusg',[]));
	//site
	queryArray.push(runQuery.makeQuery(targetObject,'config','site','siteData',[]));
	//crfEntry
	queryArray.push(runQuery.makeQuery(targetObject,'data','crfEntry','crfEntries',[]));
   
   queryArray.push(
		runQuery.makeQuery(targetObject,'config','generateConfig','generateConfigData',[]));	
	let that=this;

   let action=function(){that.addStudyData();};
	runQuery.getDataFromQueries(this,queryArray,action);
	//getDataFromQueries(queryArray,fcontinue);
}

formPortal.addStudyData=
function(){
	let config=this.config;
   //setup queryArray
	let queryArray=new Array();
   let targetObject=config.formConfig;
	
	queryArray.push(runQuery.makeQuery(targetObject,'data','StudyProperties','studyData',[]));
	let e=queryArray[queryArray.length-1];
	e.schemaName='study';
   let columnModel="";
	let varRows=config.formConfig['crfStaticVariables'].rows;
	for (let i=0;i<varRows.length;i++){
      if (i>0) columnModel+=',';
      columnModel+=varRows[i]['staticVariable'];
   }
	e.columns=columnModel;
   let that=this;
   let action=function(){that.fcontinue();};
   runQuery.getDataFromQueries(this,queryArray,action);


}

formPortal.filterEntry=
function(entry,filter,settings){
   let fName="[filterEntry]";

   if (entry.Form!=filter.form)
      return false;

   //only select forms where status matches the target status
   if (entry.FormStatus!=filter.formStatus){
      //check for additionalStates
      let addStates=filter.additionalVisibilityStates[filter.role];
      this.print(fName+' addState['+filter.role+'] '+addStates);
      if (!addStates) return false;
      if (entry.FormStatus!=addStates) return false;

   }

   this.print(fName+' candidate '+entry.entryId);
   //TODO: smart filter on user (now we get to see all)
   //
   //for editors

   if ("filterUser" in settings && filter.role=='crfEditor' && entry.UserId!=filter.userId){
      this.print(fName+' skipping identity mismatch: '+entry.UserId+'/'+filter.userId);  
      return false;
   }

   //for others
   let matchingSite=-1;
   let potentialSiteNumbers="[";
   for (let k=0;k<filter.sites.length;k++){
      if (k>0) potentialSiteNumbers+=',';
      potentialSiteNumbers+=filter.sites[k].siteNumber;
      //skip mismatching sites
      if (entry.Site!=filter.sites[k].siteNumber) continue;
      matchingSite=filter.sites[k].siteNumber;
      break;
   }
   potentialSiteNumbers+=']';
   if (matchingSite==-1){
      this.print(fName+' skipping wrong site: '+entry.Site+'/'+potentialSiteNumbers);
      return false;
   }
   return true;
}

formPortal.fcontinue=
function(){
   let fName='[fcontinue]';
   let config=this.config;
	let formConfig=config.formConfig;

	this.print(fName+" number of study data entries: "+formConfig.studyData.rows.length);
	this.print(fName+" participantId: "+formConfig.studyData.rows[0].SubjectColumnName);

	let dataForms=formConfig.dataForms.rows;

	formConfig.table=config.document.createElement("table");
	config.document.getElementById(config.div).appendChild(formConfig.table);

	let accessModeColumn=this.getMode()+'Status';
	this.print(fName+' accessModeColumn '+accessModeColumn);
	//cutting down on number of fields
   //let creatorModeColumn=getMode()+'Creator';


	//switch from status based to form based access
	this.print(fName+" forms: "+dataForms.length);
	this.print(fName+" entries: "+formConfig.crfEntries.rows.length);
	let fEntries=formConfig.crfEntries.rows;
	let users=formConfig.users.rows;
	let currentUserId=LABKEY.Security.currentUser.id;
	let currentUser=undefined;

	for (let i=0;i<users.length;i++){
		if (users[i].UserId!=currentUserId) continue;
		currentUser=users[i];
	}

   //determine the role filter
	let fList=config.role+'s';
   //check for users that fit the role, 
   //fRows lists all users for role
	let fRows=config.formConfig[fList].rows;
   this.print(fName+' candidates: '+fRows.length)
	//current user must be in the list
	
	let currentUserRoles=new Array();
	//the same user can act for multiple sites
	for (let i=0;i<fRows.length;i++){
		if (fRows[i].User!=currentUser.UserId) continue;
		currentUserRoles.push(fRows[i]);
	}

   //cludge for public sites where all users can act as anything
	let sts=config.formConfig.settings;
	let vName='allowAllForSite';
	if (vName in sts){
		let tempUserRole=new Object();
		tempUserRole.User=currentUser.UserId;
		tempUserRole.Site=parseInt(sts[vName]);
		currentUserRoles.push(tempUserRole);
	}

   //currentUser was not matched in fRows
	if (currentUserRoles.length==0){
		this.printMessage('User '+currentUser.DisplayName+" can't act as "+config.role);
		return;
	}

   //currentUser should be also attached to the site of the document
	let currentSites=new Array();
	let siteRows=config.formConfig.siteData.rows;
	for (let i=0;i<siteRows.length;i++){
		for (let j=0;j<currentUserRoles.length;j++){
			if (siteRows[i].siteNumber!=currentUserRoles[j].Site) continue;
			currentSites.push(siteRows[i]);
		}
	}

	config.formConfig.currentSites=currentSites;
	let msg='User '+currentUser.DisplayName+' acting as '+config.role+' for (';
	for (let i=0;i<currentSites.length;i++){
		if (i>0) msg+=', ';
		msg+=currentSites[i].siteName;
	}
	msg+=')';
	this.printMessage(msg);

   let filter=new Object();
   filter.role=config.role;
   filter.userId=currentUser.UserId;
   filter.sites=currentSites;


   //make a formStatus map
   let formStatusMap=new Object();
   this.print(fName+' formStatusMap: '+config.formConfig.formStatusg.rows.length);
   for (let i=0;i<config.formConfig.formStatusg.rows.length;i++){
      let fs=config.formConfig.formStatusg.rows[i];
      let s=fs['Key'];
      formStatusMap[s]=fs;
      this.print(fName+' formStatusMap adding '+s);
   }
   this.print(fName+' formStatusMap '+Object.keys(formStatusMap).length+'/'+config.formConfig.formStatusg.rows.length);

   //browse through forms
	for (let i=0;i<dataForms.length;i++){

      //dataForms is Forms
		let qForm=dataForms[i];
		let formKey=qForm.Key;
      filter.form=qForm.Key;
      
		
		//add row for each form
		let row=formConfig.table.insertRow(i);
		let formName=qForm.formName;
		this.print(fName+" ["+i+"/"+formKey+']: '+formName);

      //column counter
		let k=0;

      //get the target status
		let formStatus=qForm[accessModeColumn];
      filter.formStatus=qForm[accessModeColumn];
		this.print(fName+' target formStatus '+formStatus);

      filter.additionalVisibilityStates=new Object();
      let as=qForm["additionalVisibilityStates"];
      if (as){
         filter.additionalVisibilityStates=variableList.parseVariables(as);
      }


		for (let j=0;j<fEntries.length;j++){
         let entry=fEntries[j];
			if (!this.filterEntry(entry,filter,config.formConfig.settings))
            continue;

			//insert form
			//

			let fbox=config.document.createElement("div");
         let color='gold';
         this.print(fName+' status '+entry.FormStatus+' obj '+formStatusMap[entry.FormStatus]);
         if (formStatusMap[entry.FormStatus]){
            let c=formStatusMap[entry.FormStatus]['color'];
            if (c) color=c;
            this.print(fName+' status '+entry.FormStatus+' color '+c);
         }

			fbox.classList.add("box",color); 

			let fp=config.document.createElement("p");
			let id=entry.entryId;
			fp.innerHTML=id;
			//it would be great if this were patientId if available
			//fp.classList.add("large","center");
			fp.classList.add("center");
			fbox.appendChild(fp);
			
			let fp1=config.document.createElement("p");
			let user="NONE";
			for (let ii=0;ii<users.length;ii++){
				if (users[ii].UserId!=entry.UserId)
					continue;
				user=users[ii].DisplayName;
				break;
			}
			fp1.innerHTML=user;
			fp1.classList.add("center");
			fbox.appendChild(fp1);
			
			
			let fp2=config.document.createElement("p");
			fp2.innerHTML=formName;
			fp2.classList.add("center");
			fbox.appendChild(fp2);
			
			let fp3=config.document.createElement("p");
			fp3.id="pid"+id;
         let pid=entry['participantStudyId'];
         let loc=entry['participantLocalId'];
         let label='';
         if (pid) label+=pid+' ';
         if (loc) label+='(Local: '+loc+')';
         if (label.length==0) label="NONE";
			fp3.innerHTML=label;

			fp3.classList.add("center");
			fbox.appendChild(fp3);
			


			
			let cell=row.insertCell(k);
			cell.classList.add("stretch");
			cell.id="box"+entry.crfRef;

			let button=config.document.createElement("button");
			button.appendChild(fbox);
         let that=this;
			button.onclick=function(){that.openForm(entry)};

			cell.appendChild(button);
			k++;
		}
		this.print(fName+' finished checking existing forms');

		//only those that are allowed to create forms
		//print('Status: '+qForm[creatorModeColumn]);
		
      let creator=qForm['creator'];
      if (!creator) continue;
      if (creator!=this.getMode()) continue;
      //if (qForm[creatorModeColumn]!='TRUE') continue;

		let fbox=config.document.createElement("div");
		fbox.classList.add("box","red");

		let fp=config.document.createElement("p");
		fp.innerHTML="Create new";
		fbox.appendChild(fp);
			
			
			
		let fp2=config.document.createElement("p");
		fp2.innerHTML=formName;
		fp2.classList.add("center");
		fbox.appendChild(fp2);
			
		let cell=row.insertCell(k);
		cell.classList.add("stretch");

		let button=config.document.createElement("button");
		button.appendChild(fbox);
      let that=this;
		button.onclick=function(){that.createForm(formKey)};

		cell.appendChild(button);

	}		  
   if (config.role=='crfManager')
      this.print('Skipping form generator');
      //need formGenerator.js
      //formGenerator.addFormGenerator(this);

}

formPortal.openForm=
function(crfEntry){
   let fName="[openForm]";
   let config=this.config;
	let formConfig=config.formConfig;
	let crfRef=crfEntry.entryId;
	
	this.print(fName+" clicked for "+crfRef);

	let formId=crfEntry.Form;
	for (let i=0;i<formConfig.dataForms.rows.length;i++){
		if (formConfig.dataForms.rows[i].Key!=formId) continue;
		this.print(fName+" setting form "+formConfig.dataForms.rows[i].formName);
		formEntry=formConfig.dataForms.rows[i];
		break;
	}
	if (formEntry==undefined) return;

	//select between review and view
	//let formUrl=formEntry["formUrl"];
	//if ("reviewMode" in config) formUrl=formEntry["reviewFormUrl"];
	//print("Setting url "+formUrl);

	//direct all to the same html
	let formUrl="visit";

	reviewMode="EDIT";
	if ("reviewMode" in config) reviewMode=config.reviewMode;
	let params = {
		"name": formUrl, 
		// The destination wiki page. The name of this parameter is not arbitrary.
		"entryId": crfRef,
		"formId":formId,
		"role" : config.role
	};

	//"formSetupQuery":formEntry["setupQuery"],
	let containerPath= LABKEY.ActionURL.getContainer();
   // This changes the page after building the URL. 
	//Note that the wiki page destination name is set in params.
   var wikiURL = LABKEY.ActionURL.buildURL("crf_tecant", formUrl , containerPath, params);
   this.print(fName+" redirecting to "+wikiURL);

		 
	window.location = wikiURL;
}

formPortal.createForm=
function(formId){
   let fName="[createForm]";
   let config=this.config;
	let formConfig=config.formConfig;
   let dataForms=formConfig.dataForms.rows;
   let qForm=null;
   for (let i=0;i<dataForms.length;i++){
      if (dataForms[i].Key==formId){
         qForm=dataForms[i];
         break;
      }
   }

	this.print(fName+" create form w/id "+formId);
	
	let crfEntry=new Object();
	crfEntry.entryId=Date.now();
	crfEntry["Date"]=new Date();
	crfEntry["View"]="[VIEW]";
	crfEntry.FormStatus=qForm["initialStatus"];//In progress
   this.print(fName+" setting status to "+crfEntry.FormStatus);
	//set other variables
	//requires studyData as part of formConfig
	let studyData=formConfig.studyData.rows[0];
   let varRows=formConfig['crfStaticVariables'].rows;
   for (let i=0;i<varRows.length;i++){
      let varName=varRows[i].staticVariable;
	   crfEntry[varName]=studyData[varName];
   }
	crfEntry.UserId=LABKEY.Security.currentUser.id;
	crfEntry.Site=config.formConfig.currentSites[0].siteNumber;
	this.print(fName+" setting site to id="+crfEntry.Site);
	//from argument list
	crfEntry.Form=formId;

   let crfStatus=new Object();
   crfStatus.entryId=crfEntry.entryId;
   crfStatus.submissionDate=new Date();
   crfStatus.FormStatus=crfEntry.FormStatus;
   crfStatus.User=crfEntry.UserId;
   crfStatus.Form=crfEntry.Form;
   crfStatus.operator=config.role;
   crfStatus.action='createForm';
   let that=this;
   let cb=function(data){that.openForm(crfEntry);};
   //this is for debug
   //let cb=function(data){;};
   let containerPath=this.getContainer('data');
   let pass=function(data){formGenerator.insertRow('lists','crfStatus',crfStatus,cb,containerPath);};
   formGenerator.insertRow('lists','crfEntry',crfEntry,pass,this.getContainer('data'));
}