Documentation for this module may be created at Module:Sandbox/genewiki/generefbox/doc

local p = { }

local navbar = require('Module:Navbar')._navbar
local infobox = require('Module:Infobox3cols').infobox
local infoboxImage = require('Module:InfoboxImage').InfoboxImage



--on a page {{#invoke:Sandbox/genewiki/alllua|getTemplateData|QID=Q14865053}}
--in debug window 
--frame = mw.getCurrentFrame()
--frame.args = {QID="Q14865053"} Q18031325
--print(p.getTemplateData(frame))
p.getTemplateData = function(frame)

	--make some guesses about whether the provided QID is a good one
	--could expand here if we had some kind of error handling framework
	--did we get it from the page
	local root_qid = mw.text.trim(frame.args['QID']  or "") --try to get it from the args
	local mm_qid = ""
	--pull all the entity objects that we will need
	local	entity = {} 
	local	entity_protein = {}
	local	entity_mouse = {}
	local	entity_mouse_protein = {}
	local	checkOrtholog = "" --flag used to see if mouse data avaliable
	
	local mouse_propertyID = "P684"
	local protein_propertyID = "P688" 

	--get root gene entity
	if root_qid == "" then
		entity = mw.wikibase.getEntityObject()
		if entity then root_qid = entity.id else root_qid = "" end
			
	else
		--assuming we think its good make one call to retrieve and store its wikidata representation
		entity = mw.wikibase.getEntity(root_qid)
	end
	
  	--need to figure out if it is protein or gene here
	local subclass = p.getValue(entity, "P279") or ""
	if string.find(subclass, 'protein') then --if protein switch entity to gene
		if entity.claims then
	 		claims = entity.claims["P702"] --encoded by
	 	end
		if claims then
			--go through each index and reassign entity
			entity = {}
			if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
				for k, v in pairs(claims) do --this would be problematic if multiple genes for the protein
					local itemID = "Q" .. claims[#entity + 1].mainsnak.datavalue.value["numeric-id"]
					entity[#entity + 1] = mw.wikibase.getEntity(itemID)
					root_qid = itemID
				end
				
			end --will return nothing if no claims are found
		end
		 entity = mw.wikibase.getEntity(root_qid) 	
	 end
	
	
	--get the other related entities
	if entity then
		local claims = ""
	 	--get protein entity object
	 	if entity.claims then
	 		claims = entity.claims[protein_propertyID]
	 	end
		if claims then
			--go through each index and then make entity_protein indexed
			if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
				for k, v in pairs(claims) do
					local protein_itemID = "Q" .. claims[#entity_protein + 1].mainsnak.datavalue.value["numeric-id"]
					entity_protein[#entity_protein + 1] = mw.wikibase.getEntity(protein_itemID)
				end
				
			end --will return nothing if no claims are found
		end
	
	 	--get mouse entity object
	 	if entity.claims then
			claims = entity.claims[mouse_propertyID]
		end
		if claims then
			if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
				local mouse_itemID = "Q" .. claims[1].mainsnak.datavalue.value["numeric-id"]
				mm_qid = mouse_itemID 
				entity_mouse = mw.wikibase.getEntity(mouse_itemID)
				checkOrtholog = 1 
			end --will return nothing if no claims are found
		else
			checkOrtholog = 0
		end
	
	 	--get mouse protein entity object
	 	if entity_mouse and entity_mouse.claims then
			claims = entity_mouse.claims[protein_propertyID]
		end
	 	if claims then
	 		if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
				for k, v in pairs(claims) do
					local protein_itemID = "Q" .. claims[#entity_mouse_protein + 1].mainsnak.datavalue.value["numeric-id"]
					entity_mouse_protein[#entity_mouse_protein + 1] = mw.wikibase.getEntity(protein_itemID)
				end
			end --will return nothing if no claims are found
	 	end	
	
	end
	
	
	if entity then --only require the main gene entity
		--a list variables of all the data in the info box
		local name = p.getLabel(entity)
		local disease, dis_ref = p.getDisease(entity, "P2293")

		
		--define Global Color Scheme
		rowBGcolor = '#eee'
		titleBGcolor = '#ddd'
		sideTitleBGcolor = '#c3fdb8'

		p.createTable()
		p.renderUpperTitle(name)
		if (disease ~= "" and dis_ref ~= "") then --removes section from those items without disease info
			p.renderDiseases(disease, dis_ref, root_qid)
		end
		p.renderFooter()
   		
		return tostring(root)


	else return "An Error has occurred retrieving Wikidata item for infobox"
	end	
end

p.createTable = function(subbox)

    if subbox == 'sub' then --doesn't work 
    	 root
        	:tag('table') 
            :css('padding', '0')
            :css('border', 'none')
            :css('margin', '0')
            :css('width', 'auto')
            :css('min-width', '100%')
            :css('font-size', '100%')
            :css('clear', 'none')
            :css('float', 'none')
            :css('background-color', 'transparent')
           
    else
    	root = mw.html.create('table')
    	root
    		:addClass('infobox')
        	:css('width', '26.4em')
        	 :newline()
    end

end

-- look into entity object
p.getLabel = function(entity)
	local data = entity

	local f = {'labels','en','value'}

	local i = 1
	while true do
		local index = f[i]
		if not index then
			if type(data) == "table" then
				return mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)
			else
				return tostring(data)
			end
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return
		end
		
		i = i + 1
	end
end

--Title above image
p.renderUpperTitle = function(name)
	local title = name
    if not title then return "error: failed to get label"; end
    
    root
        :tag('tr')
            :tag('th')
                :attr('colspan', 4)
                :css('text-align', 'center')
                :css('font-size', '125%')
                :css('font-weight', 'bold')
                :wikitext(title)
                :newline()
end

p.renderDiseases = function(disease, dis_ref, Qid) 
	local title = "Genetically Related Diseases"
	local disease_title = "Disease Name"
	local source_title = "'''References'''"

	
	
	local ref_flag = {} --check each disease for a reference
	local ref_flag_all = "true" --not used in this code

    if ref_flag_all == "true" then --header section
    	root
		:tag('tr')
			:tag('td')
   				:attr('colspan', 4)
            	:css('text-align', 'center')
            	:css('background-color', rowBGcolor)
            	:newline()
		
		:tag('tr') --create title bar
			:tag('th')
			:attr('colspan', '3')
			:css('text-align', 'center')
			:css('background-color', titleBGcolor)
			:wikitext(title)
			:done()
			:newline()
		:tag('tr')
			:tag('th')
				:css('background-color', sideTitleBGcolor)
				:attr('colspan', '2')
				:wikitext(disease_title)
				:done()
				:newline()
			:tag('td')
				:css('background-color', sideTitleBGcolor)
				:attr('colspan', '2')
				:wikitext(source_title)
				:done()
				:newline()
				:done()
	end
			for index,value in ipairs(disease) do --loop through each disease 
				local i = 0
				local ref_collapse = ""
				local ref_default = ""
				local ref_link = ""
				local ref_link_list = {}
				--check to see if the reference exists if not provide link to wikidata item to add reference
				if (dis_ref[index] == nil or dis_ref[index] == '') then
					 table.insert(ref_link_list, "[[:d:"..Qid.."#P2293|click to add reference]]")
				else
			    	ref_link_list =	mw.text.split(dis_ref[index], ",")
			    end
					

					--if less than 4 don't create collapsible list
					if  table.getn(ref_link_list) < 5 then
						ref_collapse = "none"
					else	
						ref_collapse = "collapsible collapsed"
						for i =1, 5 do --get at most 4 elements to display
		     				ref_default = ref_default..table.remove(ref_link_list, 1) .. ' '
						end
						local br_count = 0
						for i =1, table.getn(ref_link_list) do --get at most 4 elements to display
		     				ref_link = ref_link..table.remove(ref_link_list, 1) .. ' '
		     
		     				if br_count < 5 then
		     					br_count = br_count + 1
		     				else
		     					br_count = 0
		     					ref_link = ref_link ..'<br>'
		     				end
						end
					end
	
					if ref_link_list[#ref_link_list] then
						ref_link = table.concat(ref_link_list, " ")
					end
			  	root
			    	:tag('tr')
   					:attr('colspan', 4)
            		:css('text-align', 'center')
            		:css('background-color', rowBGcolor)
            		:newline()
            	
					:tag('th')
							:css('background-color', rowBGcolor)
								:attr('scope', 'row')
								:attr('colspan', '2')
								:wikitext(value)
								:done()
								:newline()
					:tag('td')
						:tag('span')
						:attr('colspan', '2')
					
        				:tag('table')
            				:attr('class', ref_collapse)
            				:css('padding', '0')
            				:css('border', 'none')
            				:css('margin', '0')
            				:css('width', '100%')
            				:css('text-align', 'right')
            				:tag('tr')
            					:newline()
            					:tag('th')
            						:attr('colspan', '1')
            						:tag('span')
            							:attr('class', 'plainlinks')
            							:wikitext(ref_default)
            						:done()
            					:done()
            					:newline()
            				:done()
            				:tag('tr')
            				:tag('td')
            					:attr('colspan', '1')
            				:newline()
            				:tag('p')
            					:attr('class', 'plainlinks')
            					:wikitext(ref_link)
            				 	:newline()
            					:done()
            				:done()
            			:done()
            		:done()
        			:newline()
    			end	
    
end

local function getReference(qID, index, entity, property_id, ref_index)
	local f = {"claims",property_id,index,"references",ref_index,"snaks","P854",1,"datavalue","value"} 
	local id = qID
	--if id and (#id == 0) then
	--	id = nil
	--end
	local data = entity
	if not data then
		return nil
	end
	
    
	local i = 1
	while true do
		local index = f[i]
		if not index then
			if type(data) == "table" then
				return mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)
			else
				return tostring(data)
			end
		end
		
		data = data[index] or data[tonumber(index)]
		if not data then
			return ""
		end
		i = i + 1
	end
end

--general function to get value given an entity and property
p.getValue = function(entity, propertyID, return_val)

	local claims
	if return_val == nil then return_val = "" end
    local sep = " " --could ad as input parameter if need be
	if entity and entity.claims then
		claims = entity.claims[propertyID]
	end
	if claims then
		-- if wiki-linked value output as link if possible
		if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
			local out = {}
			for k, v in pairs(claims) do
				local datav = mw.wikibase.label("Q" .. v.mainsnak.datavalue.value["numeric-id"])
				if datav == nil then datav = " " end 
				out[#out + 1] = datav			
			end
			return table.concat(out, sep)
		else
		-- just return best values
			return entity:formatPropertyValues(propertyID).value
		end
	else
		return return_val
	end
end

p.getDisease= function(entity, propertyID)
    local claims
	if return_val == nil then return_val = "" end
	if entity and entity.claims then
		claims = entity.claims[propertyID]
	end
	if claims then
		-- if wiki-linked value output as link if possible
		
		if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then
			local out = {}
			local datasource = {}
			--{{#invoke:Wikidata |ViewSomething |id=Q18023174 |claims|P2293|1|references|1|snaks|P854|1|datavalue|value}}
			--maybe there is a more direct way to find this than looping through the json object
			
			for k, v in pairs(claims) do
				local datav = mw.wikibase.label("Q" .. v.mainsnak.datavalue.value["numeric-id"])
				
				if datav == nil then datav = " " end 
			   
				local id = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
				local linkTarget = mw.wikibase.sitelink(id)
				local refLink = ""
				local i 
				for i=1,100 do --limits to 100 references displayed
				  local ref = ""
				  ref = getReference("", k, entity, "P2293", i)
				  if (ref ~= nil and ref ~= '') then
				     refLink = refLink..",["..ref.."]"
				  --else
				  --	 refLink = "[[:d:"..Qid.."#P2293|click to add reference]]" --link to disease association section to add reference
				  end
				end
                --if refLink = "" then --skip if there isn't a reference found
				datasource[#out + 1] = refLink
				if linkTarget then
					out[#out + 1] = "[["..datav.."|"..datav.."]]"
				else
					out[#out + 1] = "[[:d:" .. id .. "|" .. datav .. "]]"
				end
				--end				
			end
			return out, datasource
		else
		-- just return best values
			--return entity:formatPropertyValues(propertyID).value
			return return_val, return_val
		end
	else
		return return_val
	end	
   return return_val
end

p.renderFooter = function()
 local text = "[[Module:Sandbox/genewiki/generefbox|Module:Sandbox/genewiki/generefbox]]"

 root
 	:tag('tr')
 		:tag('td')
 		:attr('colspan', '4')
 		:css('text-align', 'center')
 		:css('font-size','small')
 		:css('background-color', rowBGcolor)
 		:wikitext('The alternate rendering for the references can be found at line 252 in this source module ')
 		:wikitext(text)
 		:done()
 		:newline()
		:done()

end


return p