local localSeparatorStr = "," -- **lclz** Correct it if your wiki has different setting, like zhwiki uses "、" for now
local localNotApplicableStr = "n/a" -- **lclz**
local root

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

-- wrapped "protected call", return "value error" with error info on error
local function check_values
	--local u= table.upack(args)
	local exist, val = pcall(f, unpack(args))
	if exist and val ~= nil then
		return(val)
	else
		-- Leaking some debugging info won't hurt....
		return("**VALUE_ERROR** (" .. tostring(val) .. ")")
	end
end

--texts relevant to localization are tagged with --**lclz** and/or *lclz*
--on a page 
--in debug window
--frame = mw.getCurrentFrame
--frame.args = {QID="Q14865053"} Q18031325
--print(p.getTemplateData(frame))
function p.getTemplateData(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" --actually ortholog property additional orthologs can exist
	local protein_propertyID = "P688"

	--get root gene entity
	if root_qid == "" then
		entity = mw.wikibase.getEntity
		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 or ""
	if string.find or string.find then --if protein switch entity to gene **lclz**
		local claims
		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
		local qualifierID = "P703" --found in taxon
		local mouse_qual = "Q83310"
		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
					if checkOrtholog == 1 then -- Don't have to go on if we already got it
						break
					end

					local mouse_itemID = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
					local quals
					if v.qualifiers then
						quals = v.qualifiers.P703
					end
					if quals then
						for qk, qv in pairs(quals) do
							--get the taxon qualifier id
							local qual_obj_id = "Q"..qv.datavalue.value["numeric-id"]
							if qual_obj_id == mouse_qual then --check if this is mouse or other
								mm_qid = mouse_itemID
								entity_mouse = mw.wikibase.getEntity(mouse_itemID)
								checkOrtholog = 1
								break
							end
						end
					end
				end
			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 = check_values
		local bgee_wikidata_id = 'Q54985720'
		local expressed_in_tissues = check_values --P5572: expressed in
		local expressed_in_mouse_tissues = check_values --P5572: expressed in
		local entrez_gene = check_values
		local entrez_gene_mm = check_values
		local image = check_values --need to set size
		local uniprotID_hs = check_values
		local uniprotID_mm = check_values
		local pdbIDs = check_values --makes a list with links to RCSB
		local aliases = check_values
		local gene_symbol = check_values
		local hgnc_id = check_values
		local homologene_id = check_values
		local omim_id = check_values
		local mgi_id = check_values
		local ChEMBL_id = check_values
		local IUPHAR_id = check_values
		local ec_no = check_values
		local mol_funct = check_values
		local cell_comp = check_values
		local bio_process = check_values
		local expression_images = check_values
		local ensembl = check_values
		local ensembl_mm = check_values
		local refseq_mRNA = check_values
		local refseq_mRNA_mm = check_values
		local refseq_prot = check_values
		local refseq_prot_mm = check_values
		local gstart = check_values
		local gend = check_values
		local chr = check_values
		local cytoband = check_values
		local db = check_values
		local gstart_mm = check_values
		local gend_mm = check_values
		local chr_mm = check_values
		local db_mm = check_values
		local cytoband_mm = check_values
		local disease, dis_ref = p.getDisease
		local drug, drug_ref, drug_pqid, drug_pname = p.getDrug
		--local drug = check_values

		p.createTable
		p.renderUpperTitle(name)
		--p.renderCaption
		p.renderImage(image)
		p.renderAvailableStructures --PDB info
		p.renderIdentifiers
		--uncomment here to add a section of the infobox about genetically related diseases, with references
		--if (disease ~= "" and dis_ref ~= "") then --removes section from those items without disease info
		--	p.renderDiseases
		--end

		--uncomment here to add a section of the infobox about drugs that target the protein product of this gene, with references
		--if (drug ~= "" ) then --removes section from those items without drug info
		--	p.renderDrug
		--end

		if (chr ~= "" and gstart ~= "" and gend ~= "") or (chr_mm ~= "" and gstart_mm ~= "" and gend_mm ~= "") then
			p.renderGeneLocation
		end
		if expression_images ~= "" or expressed_in_tissues ~= localNotApplicableStr then
			p.renderRNAexpression
		end
		if (mol_funct ~= "" and cell_comp ~= "" and bio_process ~= "") then
			p.renderGeneOntology
		end
		p.renderOrthologs
		p.renderFooter

		return tostring(root)
		--return table.concat(drug_pqid)

	else
		return "정보 상자를 위한 위키데이터 항목을 검색하는 중 오류가 발생했습니다"
	end
end

function p.createTable(subbox)

	if subbox == 'sub' then --doesn't work
		root

	else
		root = mw.html.create('table')
		root
			-- *lclz*: Some projects, like zhwiki (again), use inline styles on
			-- infobox modules in addition to the class. Be sure to check them out.
	end

end

--Title above image
function p.renderUpperTitle(name)
	local title = name
	if not title then return "error: failed to get label"; end

	root
end

--This is a place holder for the image caption, which is stored in wikicommons comments unsure how to access
function p.renderCaption(entity)
	--caption
end

--gets default image
function p.renderImage(image)
	root
end

function p.renderAvailableStructures

	local title = '사용 가능한 구조' --**lclz**
	local pdb_link = "PDB" --**lclz**
	local searchTitle = ""
	local listTitle = "PDB ID 코드 목록" --**lclz**
	local PDBe_base = 'https://www.ebi.ac.uk/pdbe/searchResults.html?display=both&amp;term='
	local RCSB_base = 'https://www.rcsb.org/search?q='
					..'rcsb_polymer_entity_container_identifiers.reference_sequence_identifiers.database_name:UniProt%20AND%20'
					..'rcsb_polymer_entity_container_identifiers.reference_sequence_identifiers.database_accession:'
	local url_uniprot = " "

	if checkOrtholog == 1 and uniprotID_mm ~= 'n/a' then
		searchTitle = '동원체 검색: ' --**lclz**
		url_uniprot = uniprotID_mm..','..uniprotID_hs
	else
		searchTitle = '인간 유니프롯 검색: ' --**lclz**
		url_uniprot = uniprotID_hs
	end
	local PDBe_list = " " --create a list with " or " if there is more than one uniprot
	--get first uniprot in a list
	if url_uniprot:match(",") then--first check if there is a list if not just assume one value
		PDBe_list = string.gsub --add or's inststead of commas
	else
		PDBe_list = url_uniprot
	end

	local PDBe = "["..PDBe_base..PDBe_list.." PDBe] "
	local RCSB = "["..RCSB_base..url_uniprot.." RCSB] "

	if string.match then --if there aren't any PDB_ID don't display this part of the infobox
		--p.formatRow(title)---how to not close the tags is a mystery and I could condense code once I figure out
		root

	else
		return ""
	end
end

function p.renderIdentifiers
	local title = "식별자" --**lclz**
	local label_aliases = "다른 이름" --**lclz**
	local symbol_url
	if gene_symbol == "" or gene_symbol == nil then
		symbol_url = ""
	else
		if hgnc_id == "" or hgnc_id == nil then
			symbol_url = gene_symbol

		else
			symbol_url = "[https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/"..hgnc_id.." "..gene_symbol.."]"
		end
	end

	-- *lclz*: see getAliases. You can, say, use another punctuation for your language.
	aliases = string.gsub --get rid of gene name if last in alias list
	aliases = string.gsub --get rid of gene name if first in aliases list
	aliases = string.gsub --get rid of gene name if in aliases list
	aliases = string.gsub --remove comma from middle
	aliases = string.gsub --remove comma from end
	local label_ext_id = "외부 ID" --**lclz**

	omim_id = string.gsub
	local omim_list = mw.text.split
	local omim = ""
	if (omim_id ~= nil and omim_id ~= "") then
		omim = "OMIM"..": " --**lclz**
	end
	for i, v in ipairs(omim_list) do
		if string.match then
			omim = omim.."[https://omim.org/entry/"..v.." "..v.."], "
		end
	end
	omim = string.gsub --remove comma from end

	homologene_id = string.gsub
	local homolo_list = mw.text.split
	local homolo =""
	if (homologene_id ~= nil and homologene_id ~= "") then
		homolo = "HomoloGene"..": "
	end
	for i, v in ipairs(homolo_list) do
		if string.match then
			homolo = homolo.."[https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=homologene&dopt=HomoloGene&list_uids="..v.." "..v.."] "
		end
	end
	homolo = string.gsub --remove comma from end

	local genecards = "GeneCards"..": "
	genecards = genecards.."[https://www.genecards.org/cgi-bin/carddisp.pl?gene="..gene_symbol.." "..gene_symbol.."] "

	mgi_id = string.gsub
	local mgi_list = mw.text.split
	local mgi = ""
	if (mgi_id ~= nil and mgi_id ~= "") then
		mgi = "MGI"..": " --**lclz**
	end
	for i, v in ipairs(mgi_list) do
		if string.match then
			local mgi_number = string.sub
			mgi = mgi.."[http://www.informatics.jax.org/marker/"..mgi_id.." "..mgi_number.."] "
		end
	end
	mgi = string.gsub--remove comma from end

	local ChEMBL = ""
	if string.match then
		ChEMBL = "ChEMBL"..": ".."[https://www.ebi.ac.uk/chembldb/index.php/target/inspect/CHEMBL"..ChEMBL_id.." "..ChEMBL_id.."] "
	end
	local IUPHAR = ""
	if string.match then
		IUPHAR = "IUPHAR"..": ".."[http://www.guidetopharmacology.org/GRAC/ObjectDisplayForward?objectId="..IUPHAR_id.." "..IUPHAR_id.."] " --**lclz**
	end -- *lclz*
	local label_EC = "EC 번호" --**lclz**
	ec_no = string.gsub--remove those with"-" in list
	ec_no = string.gsub--remove those with"-" not in list
	local link_ec_no = string.gsub --create format for link

	local EC = "[https://www.genome.jp/dbget-bin/www_bget?enzyme+" .. link_ec_no .. " " .. ec_no .. "]"

	root


	if ec_no ~= "" then
		root
	end
end

function p.renderDiseases
	local title = "유전관련질환" --**lclz**

	--check first to see if any of the diseases have references
	local ref_flag_all = false --check if any disease have references if not then don't render the headers
	local disease_name = '' --local disease_name = table.concat
	for index,value in ipairs(disease) do
		if (dis_ref[index] ~= nil and dis_ref[index] ~= '') then
			if disease_name == '' then
				disease_name = value
			else
				disease_name = disease_name..", "..value -- *lclz*: punctuation
			end
			ref_flag_all = true
		end
	end
	if ref_flag_all then
		root

		local ref_url = "https://www.wikidata.org/wiki/"..qid.."#P2293" --direct page to property genetically associated disease
		local title = name.."의 유전 관련 질병의 위키데이터 각주 보기/편집" --**lclz**
		local ref_link = disease_name..frame:extensionTag

		root
	end
end

function p.renderDrug
	local title = "유효 약제" --**lclz**

	--check first to see if any of the drugs have references
	local ref_flag_all = false --check if any drugs have references if not then don't render the headers
	local drug_list_per_protein = {} -- a list of lists of drugs to put in reference string each protein will have a list
	--for i,v in ipairs(drug_pqid) do -- set all lists keys to empty so can append without key errors

	--end
	for index,value in ipairs(drug) do
		if (drug_ref[index] ~= nil and drug_ref[index] ~= '') then
			local protein_qid = drug_pqid[index]
			if drug_list_per_protein[protein_qid] == '' or drug_list_per_protein[protein_qid] == nil then
				drug_list_per_protein[protein_qid] = value
			else
				-- *lclz*: comma
				drug_list_per_protein[protein_qid] = drug_list_per_protein[protein_qid]..', '..value --each list of drugs keyed on protein qid
			end
			ref_flag_all = true
		end
	end

	if ref_flag_all then
		root

		--loop to create reference links from drug lists
		for k,v in pairs(drug_list_per_protein) do
			local drug_name = v
			local ref_url = "https://www.wikidata.org/wiki/"..k.."#P129" --direct page to property genetically associated disease
			local title = drug_pname[k].."의 물리적 상호작용을 하는 약제의 위키데이터 각주 보기/편집" --**lclz**
			local ref_link = drug_name..frame:extensionTag

			root
		end
	end

end

function p.renderGeneLocation
		local titleHuman = "유전자 위치 (인간)" --**lclz**
		local titleMouse = "유전자 위치 (쥐)" --**lclz**
		local label_chr = "염색체" --**lclz**
		local label_locus = "자리" --**lclz**
		local label_gstart = "시작" --**lclz**
		local label_gend = "끝" --**lclz**
		local tooltip_arrowSign = name.."의 유전자 위치" --**lclz**
		local arrowSign_width = 14

	if chr ~= "" and gstart ~= "" and gend ~= "" then
		--Chromosome lengths are from GRCh38.p10 https://www.ncbi.nlm.nih.gov/grc/human/data?asm=GRCh38.p10
		--This table is used only for calculating "Where should red-rectangle put?"
		--Curretly, Aug 2017, it seems all gene data, which are stored in Wikidata, have start/end positions based on GRCh38.
		local chrLengthTable = {}
				chrLengthTable["1"] = 248956422
				chrLengthTable["2"] = 242193529
				chrLengthTable["3"] = 198295559
				chrLengthTable["4"] = 190214555
				chrLengthTable["5"] = 181538259
				chrLengthTable["6"] = 170805979
				chrLengthTable["7"] = 159345973
				chrLengthTable["8"] = 145138636
				chrLengthTable["9"] = 138394717
				chrLengthTable["10"] = 133797422
				chrLengthTable["11"] = 135086622
				chrLengthTable["12"] = 133275309
				chrLengthTable["13"] = 114364328
				chrLengthTable["14"] = 107043718
				chrLengthTable["15"] = 101991189
				chrLengthTable["16"] = 90338345
				chrLengthTable["17"] = 83257441
				chrLengthTable["18"] = 80373285
				chrLengthTable["19"] = 58617616
				chrLengthTable["20"] = 64444167
				chrLengthTable["21"] = 46709983
				chrLengthTable["22"] = 50818468
				chrLengthTable["X"] = 156040895
				chrLengthTable["Y"] = 57227415
				chrLengthTable["MT"] = 16569
		local chrLength = chrLengthTable[chr]

		--Different languages have different word order.
		local chrTextTable = {} --**lclz** linked articles
				chrTextTable["1"] = "1번 염색체"
				chrTextTable["2"] = "2번 염색체"
				chrTextTable["3"] = "3번 염색체"
				chrTextTable["4"] = "4번 염색체"
				chrTextTable["5"] = "5번 염색체"
				chrTextTable["6"] = "6번 염색체"
				chrTextTable["7"] = "7번 염색체"
				chrTextTable["8"] = "8번 염색체"
				chrTextTable["9"] = "9번 염색체"
				chrTextTable["10"] = "10번 염색체"
				chrTextTable["11"] = "11번 염색체"
				chrTextTable["12"] = "12번 염색체"
				chrTextTable["13"] = "13번 염색체"
				chrTextTable["14"] = "14번 염색체"
				chrTextTable["15"] = "15번 염색체"
				chrTextTable["16"] = "16번 염색체"
				chrTextTable["17"] = "17번 염색체"
				chrTextTable["18"] = "18번 염색체"
				chrTextTable["19"] = "19번 염색체"
				chrTextTable["20"] = "20번 염색체"
				chrTextTable["21"] = "21번 염색체"
				chrTextTable["22"] = "22번 염색체"
				chrTextTable["X"] = "X 염색체"
				chrTextTable["Y"] = "Y 염색체"
				chrTextTable["MT"] = "미토콘드리아 DNA"
		local chrText = chrTextTable[chr]

		--about the calculation below, see https://en.wikipedia.org/wiki/User:Was_a_bee/Gene#3._Calculation_detail
		local markerWidth = ((gend - gstart) * 294.133 )/ chrLength
		if markerWidth < 2 then
			markerWidth = 2
		else
			markerWidth = math.ceil(markerWidth)
		end
		local markerLocation = (147.0666 * (gstart + gend) / chrLength ) + 1.6 - (markerWidth / 2)
		local arrowSignLocation = markerLocation + (markerWidth / 2) - (arrowSign_width / 2)
		markerLocation = math.floor( markerLocation * 10 + 0.5 ) / 10

		local source_link_chr, source_link_gstart, source_link_gend
		if( db == "hg38" ) then
			source_link_chr = frame:extensionTag --**lclz**
			source_link_gstart = frame:extensionTag
			source_link_gend = frame:extensionTag
		elseif( db == "hg37") then
			source_link_chr = frame:extensionTag --**lclz**
			source_link_gstart = frame:extensionTag
			source_link_gend = frame:extensionTag
		else
			source_link_chr = ""
			source_link_gstart = ""
			source_link_gend = ""
		end

		local wikitext_for_ideogram_image = "" --wikitext used for showing gene location
		if chr == "MT" then -- wikitext for mitochondrial DNA
			--wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			--wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			--wikitext_for_ideogram_image = wikitext_for_ideogram_image..""

		else -- wikitext for autosome and sex chromosome
			wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			wikitext_for_ideogram_image = wikitext_for_ideogram_image.."300px|"..chrText..""
			wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
			wikitext_for_ideogram_image = wikitext_for_ideogram_image..""
		end

	root
	end

	if chr_mm ~= "" and gstart_mm ~= "" and gend_mm ~= "" then
		--Chromosome lengths are from GRCm38.p5 https://www.ncbi.nlm.nih.gov/grc/mouse/data?asm=GRCm38.p5
		local chrLengthTable_mm = {}
				chrLengthTable_mm["1"] = 195471971
				chrLengthTable_mm["2"] = 182113224
				chrLengthTable_mm["3"] = 160039680
				chrLengthTable_mm["4"] = 156508116
				chrLengthTable_mm["5"] = 151834684
				chrLengthTable_mm["6"] = 149736546
				chrLengthTable_mm["7"] = 145441459
				chrLengthTable_mm["8"] = 129401213
				chrLengthTable_mm["9"] = 124595110
				chrLengthTable_mm["10"] = 130694993
				chrLengthTable_mm["11"] = 122082543
				chrLengthTable_mm["12"] = 120129022
				chrLengthTable_mm["13"] = 120421639
				chrLengthTable_mm["14"] = 124902244
				chrLengthTable_mm["15"] = 104043685
				chrLengthTable_mm["16"] = 98207768
				chrLengthTable_mm["17"] = 94987271
				chrLengthTable_mm["18"] = 90702639
				chrLengthTable_mm["19"] = 61431566
				chrLengthTable_mm["X"] = 171031299
				chrLengthTable_mm["Y"] = 91744698
				chrLengthTable_mm["MT"] = 16299
		local chrLength_mm = chrLengthTable_mm[chr_mm]

		--Different languages have different word order.
		local chrTextTable_mm = {}--**lclz** Articles not yet created
				chrTextTable_mm["1"] = "1번 염색체 (쥐)"
				chrTextTable_mm["2"] = "2번 염색체 (쥐)"
				chrTextTable_mm["3"] = "3번 염색체 (쥐)"
				chrTextTable_mm["4"] = "4번 염색체 (쥐)"
				chrTextTable_mm["5"] = "5번 염색체 (쥐)"
				chrTextTable_mm["6"] = "6번 염색체 (쥐)"
				chrTextTable_mm["7"] = "7번 염색체 (쥐)"
				chrTextTable_mm["8"] = "8번 염색체 (쥐)"
				chrTextTable_mm["9"] = "9번 염색체 (쥐)"
				chrTextTable_mm["10"] = "10번 염색체 (쥐)"
				chrTextTable_mm["11"] = "11번 염색체 (쥐)"
				chrTextTable_mm["12"] = "12번 염색체 (쥐)"
				chrTextTable_mm["13"] = "13번 염색체 (쥐)"
				chrTextTable_mm["14"] = "14번 염색체 (쥐)"
				chrTextTable_mm["15"] = "15번 염색체 (쥐)"
				chrTextTable_mm["16"] = "16번 염색체 (쥐)"
				chrTextTable_mm["17"] = "17번 염색체 (쥐)"
				chrTextTable_mm["18"] = "18번 염색체 (쥐)"
				chrTextTable_mm["19"] = "19번 염색체 (쥐)"
				chrTextTable_mm["X"] = "X 염색체 (쥐)"
				chrTextTable_mm["Y"] = "Y 염색체 (쥐)"
				chrTextTable_mm["MT"] = "미토콘드리아 DNA (쥐)"
		local chrText_mm = chrTextTable_mm[chr_mm]

		--about the calculation below, see https://en.wikipedia.org/wiki/User:Was_a_bee/Gene#3._Calculation_detail
		local markerWidth_mm = ((gend_mm - gstart_mm) * 294.133 )/ chrLength_mm
		if markerWidth_mm < 2 then
			markerWidth_mm = 2
		else
			markerWidth_mm = math.ceil(markerWidth_mm)
		end
		local markerLocation_mm = (147.0666 * (gstart_mm + gend_mm) / chrLength_mm ) + 1.6 - (markerWidth_mm / 2)
		local arrowSignLocation_mm = markerLocation_mm + (markerWidth_mm / 2) - (arrowSign_width / 2)
		markerLocation_mm = math.floor( markerLocation_mm * 10 + 0.5 ) / 10
		local source_link_chr_mm = ""
		local source_link_gstart_mm = ""
		local source_link_gend_mm = ""
		if( db_mm == "mm10" or db_mm == "mm0") then
			--"mm0" happens because of function "getAliasFromGenomeAssembly" is not prepared for mouse data.
			--But as of now, Aug. 2017, it seems that all data which is stored in Wikidata are based on GRCm38/mm10.
			--So treating mouse genomic data as GRCm38/mm10 if not specified.
			source_link_chr_mm = frame:extensionTag --**lclz**
			source_link_gstart_mm = frame:extensionTag
			source_link_gend_mm = frame:extensionTag
			else
			source_link_chr_mm = ""
			source_link_gstart_mm = ""
			source_link_gend_mm = ""
		end
		local wikitext_for_ideogram_image_mm = "" --wikitext used for showing gene location
		if chr_mm == "MT" then -- wikitext for mitochondrial DNA
			--wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			--wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			--wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""

		else -- wikitext for autosome and sex chromosome
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm.."300px|"..chrText_mm..""
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
			wikitext_for_ideogram_image_mm = wikitext_for_ideogram_image_mm..""
		end

	root
	end
end

--Get the render elements collapse option, collapsed anatomic entities (defaut text),
--and anatomic entity list for the gene expression list rendering.
function p.renderExpressionList
	--create list of expressed in anatomic entities
	if default_text == nil then default_text = "" end
	local anatomic_entity_labels = localNotApplicableStr
	local collapse = "none"
	local split_values = mw.text.split
	local anatomic_entity_list = {}
	local anatomic_entities = {}
	local results
	for k,v in ipairs(split_values) do
		if string.match and v ~= localNotApplicableStr then
			anatomic_entity_list[#anatomic_entity_list+1] = ""
			anatomic_entities[#anatomic_entities+1] = v
		end
	end
	--if less than 11 don't create collapsible list
	if table.getn(anatomic_entity_list) < 11 then
		if table.getn(anatomic_entity_list) == 0 then
			anatomic_entity_labels = localNotApplicableStr
			default_text = ""
		end
	else
		collapse = "collapsible collapsed"
		default_text = default_text .. ''--get first 5 elements in table and use for display
	end
	if anatomic_entity_list[#anatomic_entity_list] then
		anatomic_entity_labels = table.concat
	end
	results = {collapse, default_text, anatomic_entity_labels}
	return results
end

function p.renderRNAexpression
	local bgee_gene_page = "https://bgee.org/gene/"
	local title = "RNA 발현 패턴" --**lclz**
	local biogps_link = ""
	local biogps_title = "BioGPS"
	biogps_title = "[http://biogps.org/ " .. biogps_title .. "]"
	-- If no expression image exist in BioGPS, the N/A is displayed
	if expression_images ~= "" then
		biogps_link = "[http://biogps.org/gene/"..entrez_gene.."/ 추가 참조 발현 데이터]" --**lclz**
	else
		expression_images = localNotApplicableStr
	end
	local ensembl_id = string.match or ""
	local ensembl_id_mouse = string.match or ""
	local bgee_title = "Bgee"
	bgee_title = "[https://bgee.org/ " .. bgee_title .. "]"
	local bgee_default = "["..bgee_gene_page..ensembl_id.." 최상위 발현]"
	bgee_expression = p.renderExpressionList
	local bgee_collapse = bgee_expression[1]
	bgee_default = bgee_expression[2]
	local bgee_tissues = bgee_expression[3]
	local bgee_default_mm = "["..bgee_gene_page..ensembl_id_mouse.." 최상위 발현]"
	bgee_expression_mouse = p.renderExpressionList
	local bgee_collapse_mm = bgee_expression_mouse[1]
	bgee_default_mm = bgee_expression_mouse[2]
	local bgee_tissues_mm = bgee_expression_mouse[3]
	local bgee_more_link = ""
	if bgee_tissues ~= localNotApplicableStr then
		bgee_more_link = "["..bgee_gene_page..ensembl_id.." 추가 참조 발현 데이터]"
	end

	root
end

function p.renderGeneOntology
	local title = "유전자 온톨로지" --**lclz**
	local mol_funct_title = "분자 함수" --**lclz**
	local cell_comp_title = "세포 성분" --**lclz**
	local bio_process_title = "생물학적 과정" --**lclz**
	local amigo_link = "[http://amigo.geneontology.org/" .. " Amigo]"
	local quickGO_link = "[https://www.ebi.ac.uk/QuickGO/" .. " QuickGO]"

	root

end

function p.renderOrthologs
	local title = "동원체" --**lclz**
	--to do make the list creation a function
	--create list for entrez ids

	local category_chromosome = ''
	if chr == "" then
		category_chromosome = '분류:인간 염색체 유전자'-- *lclz*: Category name
	elseif chr == "MT" then
		category_chromosome = '분류:인간 미토콘드리아 유전자'-- *lclz*: Category name for mtDNA genes
	elseif chr == "X" or chr == "Y" then
		category_chromosome = '분류:인간 '..chr..' 염색체상 유전자'-- *lclz*: Category name
	else
		category_chromosome = '분류:인간 '..chr..'번 염색체상 유전자'-- *lclz*: Category name
	end
	if mw.title.getCurrentTitle.namespace ~= 0 then
		category_chromosome = ""
	end
	local entrezTitle = "앙트레"
	entrez_gene = string.gsub
	local entrez_link = localNotApplicableStr
	local entrez_collapse
	local entrez_default = ""
	local split_entrez = mw.text.split
	local entrez_link_list = {}
	for k,v in ipairs(split_entrez) do
		if string.match and v ~= localNotApplicableStr then
			entrez_link_list[#entrez_link_list+1] = "[https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&amp;cmd=retrieve&amp;dopt=default&amp;list_uids="..entrez_gene.."&amp;rn=1 "..entrez_gene.."]"
		end
	end
	--if less than 5 don't create collapsible list
	if table.getn(entrez_link_list) < 5 then
		entrez_collapse = "none"
		if entrez_default == nil and table.getn(entrez_link_list) == 0 then entrez_link = localNotApplicableStr end
	else
		entrez_collapse = "collapsible collapsed"
		entrez_default = table.remove .. ''--get first 5 elements in table and use for display
	end
	if entrez_link_list[#entrez_link_list] then
		entrez_link = table.concat
	end

	--create list for mouse Entrez id
	entrez_gene_mm = string.gsub
	local entrez_mm_link = localNotApplicableStr
	local entrez_mm_collapse
	local entrez_mm_default = ""
	local split_entrez_mm = mw.text.split
	local entrez_mm_link_list = {}
	for k,v in ipairs(split_entrez_mm) do
		if string.match and v ~= localNotApplicableStr then
			entrez_mm_link_list[#entrez_mm_link_list+1] = "[https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&amp;cmd=retrieve&amp;dopt=default&amp;list_uids="..v.."&amp;rn=1 "..v.."]"
		end
	end
	--if less than 5 don't create collapsible list
	if table.getn(entrez_mm_link_list) < 5 then
		entrez_mm_collapse = "none"
		if entrez_mm_default == nil and table.getn(entrez_mm_link_list) == 0 then entrez_mm_link = localNotApplicableStr end
	else
		entrez_mm_collapse = "collapsible collapsed"
		entrez_mm_default = table.remove .. ''--get first 5 elements in table and use for display
	end
	if entrez_mm_link_list[#entrez_mm_link_list] then
		entrez_mm_link = table.concat
	end

	--create list of ensembl id
	local ensemblTitle = "앙상블"
	ensembl = string.gsub
	local ensembl_link = localNotApplicableStr
	local ensembl_collapse
	local ensembl_default = ""
	local split_ensembl = mw.text.split
	local ensembl_link_list = {}
	for k,v in ipairs(split_ensembl) do
		if string.match and v ~= localNotApplicableStr then
			ensembl_link_list[#ensembl_link_list+1] = "[http://www.ensembl.org/Homo_sapiens/geneview?gene="..v..";db=core".." "..v.."]"
		end
	end
	--if less than 5 don't create collapsible list
	if table.getn(ensembl_link_list) < 5 then
		ensembl_collapse = "none"
		if ensembl_default == nil and table.getn(ensembl_link_list) == 0 then ensembl_link = localNotApplicableStr end
	else
		ensembl_collapse = "collapsible collapsed"
		ensembl_default = table.remove .. ''--get first 5 elements in table and use for display
	end
	if ensembl_link_list[#ensembl_link_list] then
		ensembl_link = table.concat
	end

	--create list of mouse ensembl id
	ensembl_mm = string.gsub
	local ensembl_mm_link = localNotApplicableStr
	local ensembl_mm_collapse
	local ensembl_mm_default = ""
	local split_ensembl_mm = mw.text.split
	local ensembl_mm_link_list = {}
	for k,v in ipairs(split_ensembl_mm) do
		if string.match and v ~= localNotApplicableStr then
			ensembl_mm_link_list[#ensembl_mm_link_list+1] = "[http://www.ensembl.org/Mus_musculus/geneview?gene="..v..";db=core".." "..v.."]"
		end
	end
	--if less than 5 don't create collapsible list
	if table.getn(ensembl_mm_link_list) < 5 then
		ensembl_mm_collapse = "none"
		if ensembl_mm_default == nil and table.getn(ensembl_mm_link_list) == 0 then ensembl_mm_link = localNotApplicableStr end
	else
		ensembl_mm_collapse = "collapsible collapsed"
		ensembl_mm_default = table.remove .. ''--get first 5 elements in table and use for display
	end
	if ensembl_mm_link_list[#ensembl_mm_link_list] then
		ensembl_mm_link = table.concat
	end

	--create lists of uniprot ID
	local uniprotTitle = "유니프롯"
	local uniprot_url = "https://www.uniprot.org/uniprot/"

	local uniprot_link = localNotApplicableStr
	local uniprot_collapse
	local uniprot_default = ""
	--split string and loop through concatenate by 
	local split_uniprot = mw.text.split -- the separator may be different sometimes, see note on zhwiki. This is unlikely to have punctuation, prayer.
	local uniprot_link_list = {}
	local uniprot_first = {} --preferred values only display [O,P,Q] prefixed entries if they exist
	local uniprot_alternate = {} --[A-N,R-Z] entries
	local hash = {} --storage to look for duplicated values
	for k,v in ipairs(split_uniprot) do
		if not hash[v] then --only add if not found previously..some encodes uniprotID dup in different encodes
			local label = mw.text.trim(v)
			local concat_uniprot_link = uniprot_url .. label
			if string.match and v ~= localNotApplicableStr then
				if string.match or string.match or string.match then
					uniprot_first[#uniprot_first+1] = "[" .. concat_uniprot_link .. " " ..label .. "]"
				else
					uniprot_alternate[#uniprot_alternate+1] = "[" .. concat_uniprot_link .. " " ..label .. "]"
				end
			end
			hash[v] = true
		end
	end
	if table.getn(uniprot_first)>0 then --if there is something in the preferred values display else display anything else
		uniprot_link_list = uniprot_first
	else
		uniprot_link_list = uniprot_alternate
	end

	--if less than 5 don't create collapsible list
	if table.getn(uniprot_link_list) < 5 then
		uniprot_collapse = "none"
		if uniprot_default == nil and table.getn(uniprot_link_list) == 0 then uniprot_link = localNotApplicableStr end
	else
		uniprot_collapse = "collapsible collapsed"
		uniprot_default = table.remove .. ''--get first 5 elements in table and use for display
	end

	if uniprot_link_list[#uniprot_link_list] then
		uniprot_link = table.concat
	end

	--mouse uniprot lists
	local uniprot_mm_link = localNotApplicableStr
	local uniprot_mm_collapse
	local uniprot_mm_default = ""
	--split string and loop through concatenate by 
	local split_uniprot_mm = mw.text.split
	local uniprot_mm_link_list = {}
	local uniprot_mm_first = {} --preferred values only display [O,P,Q] prefixed entries if they exist
	local uniprot_mm_alternate = {} --[A-N,R-Z] entries
	local hash = {} --storage to look for duplicated values
	for k,v in ipairs(split_uniprot_mm) do
		if not hash[v] then --only add if not found previously..some encodes uniprotID dup in different encodes
			local label = mw.text.trim(v)
			local concat_uniprot_link = uniprot_url .. label
			if string.match and v ~= localNotApplicableStr then
				if string.match or string.match or string.match then
					uniprot_mm_first[#uniprot_mm_first+1] = "[" .. concat_uniprot_link .. " " ..label .. "]"
				else
					uniprot_mm_alternate[#uniprot_mm_alternate+1] = "[" .. concat_uniprot_link .. " " ..label .. "]"
				end
			end
			hash[v] = true
		end
	end
	if table.getn(uniprot_mm_first)>0 then --if there is something in the preferred values display else display anything else
		uniprot_mm_link_list = uniprot_mm_first
	else
		uniprot_mm_link_list = uniprot_mm_alternate
	end

	--if less than 5 don't create collapsible list
	if table.getn(uniprot_mm_link_list) < 5 then
		uniprot_mm_collapse = "none"
		if uniprot_mm_default == nil and table.getn(uniprot_mm_link_list) == 0 then uniprot_mm_link = localNotApplicableStr end
	else
		uniprot_mm_collapse = "collapsible collapsed"
		uniprot_mm_default = table.remove .. ''--get first 5 elements in table and use for display
	end

	if uniprot_mm_link_list[#uniprot_mm_link_list] then
		uniprot_mm_link = table.concat
	end

	local ncbi_link = "https://www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?val="
	local refseq_mRNATitle = "RefSeq (mRNA)" -- *lclz*: sometimes

	--create list of links for refSeq mRNA
	local refseq_mRNA_link = localNotApplicableStr
	local refseq_mRNA_collapse
	local refseq_mRNA_default = ""
	--split string and loop through concatenate by 
	local split_refseq_mRNA = mw.text.split
	local link_list_first = {} --hold those the have NM or NP values
	local link_list_alternate = {} --hold those that are XM or XP values
	local link_list = {} --if NM,NP display if not display XM, XP values
	for k,v in ipairs(split_refseq_mRNA) do
		local label = mw.text.trim(v)
		local concat_ncbi_link = ncbi_link .. label
		if string.match and v ~= localNotApplicableStr then
			if string.match or string.match then
				link_list_first[#link_list_first+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			elseif string.match or string.match then
				link_list_alternate[#link_list_alternate+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			end
		end
	end
	if table.getn(link_list_first)>0 then
		link_list = link_list_first
	else
		link_list = link_list_alternate
	end

	--if less than 5 don't create collapsible list
	if table.getn(link_list) < 6 then
		refseq_mRNA_collapse = "none"
		if refseq_mRNA_default == nil and table.getn(link_list) == 0 then refseq_mRNA_link = localNotApplicableStr end
	else
		refseq_mRNA_collapse = "collapsible collapsed"
		refseq_mRNA_default = table.remove .. ''--get first 5 elements in table and use for display
	end

	if link_list[#link_list] then
		refseq_mRNA_link = table.concat
	end

	--create list of links for refSeq mRNA for mouse
	local refseq_mRNA_mm_link = localNotApplicableStr
	local refseq_mRNA_mm_collapse
	local refseq_mRNA_mm_default = ""
	local split_refseq_mRNA_mm = mw.text.split
	local link_list_mm = {} --if NM,NP display if not display XM, XP values
	local link_list_first = {} --hold those the have NM or NP values
	local link_list_alternate = {} --hold those that are XM or XP values

	for k,v in ipairs(split_refseq_mRNA_mm) do
		local label = mw.text.trim(v)
		local concat_ncbi_link = ncbi_link .. label
		if string.match and v ~= localNotApplicableStr then
			if string.match or string.match then
				link_list_first[#link_list_first+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			elseif string.match or string.match then
				link_list_alternate[#link_list_alternate+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			end
		end
	end
	if table.getn(link_list_first)>0 then
		link_list_mm = link_list_first
	else
		link_list_mm = link_list_alternate
	end
	--if less than 5 don't create collapsible list
	if table.getn(link_list_mm) < 6 then
		refseq_mRNA_mm_collapse = "none"
		if refseq_mRNA_mm_default == nil and table.getn(link_list_mm) == 0 then refseq_mRNA_mm_link = localNotApplicableStr end
	else
		refseq_mRNA_mm_collapse = "collapsible collapsed"
		refseq_mRNA_mm_default = table.remove .. ''--get first 5 elements in table and use for display
	end

	if link_list_mm[#link_list_mm] then
		refseq_mRNA_mm_link = table.concat
	end

	-- *lclz*: sometimes
	local refseq_protTitle = "RefSeq(단백질)"
	--create list of links for human refseq protein
	local refseq_prot_link = localNotApplicableStr
	local refseq_prot_collapse
	local refseq_prot_default = ""
	local split_refseq_prot = mw.text.split
	local link_list_prot = {}
	local link_list_first = {} --hold those the have NM or NP values
	local link_list_alternate = {} --hold those that are XM or XP values
	for k,v in ipairs(split_refseq_prot) do
		local label = mw.text.trim(v)
		local concat_ncbi_link = ncbi_link .. label
		if string.match and v ~= localNotApplicableStr then
			if string.match or string.match then
				link_list_first[#link_list_first+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			elseif string.match or string.match then
				link_list_alternate[#link_list_alternate+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			end
		end
	end
	if table.getn(link_list_first)>0 then
		link_list_prot = link_list_first
	else
		link_list_prot = link_list_alternate
	end
	--if less than 5 don't create collapsible list
	if table.getn(link_list_prot) < 6 then
		refseq_prot_collapse = "none"
		if refseq_prot_default == nil and table.getn(link_list_prot) == 0 then refseq_prot_link = localNotApplicableStr end
	else
		refseq_prot_collapse = "collapsible collapsed"
		refseq_prot_default = table.remove .. ''--get first 5 elements in table and use for display
	end

	if link_list_prot[#link_list_prot] then
		refseq_prot_link = table.concat
	end

	--create list of links for mouse refseq protein
	local refseq_prot_mm_link = localNotApplicableStr
	local refseq_prot_mm_collapse
	local refseq_prot_mm_default = ""
	local split_refseq_prot_mm = mw.text.split
	local link_list_prot_mm = {}
	local link_list_first = {} --hold those the have NM or NP values
	local link_list_alternate = {} --hold those that are XM or XP values

	for k,v in ipairs(split_refseq_prot_mm) do
		local label = mw.text.trim(v)
		local concat_ncbi_link = ncbi_link .. label
		if string.match and v ~= localNotApplicableStr then
			if string.match or string.match then
				link_list_first[#link_list_first+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			elseif string.match or string.match then
				link_list_alternate[#link_list_alternate+1] = "[" .. concat_ncbi_link .. " " ..label .. "]"
			end
		end
	end
	if table.getn(link_list_first)>0 then
		link_list_prot_mm = link_list_first
	else
		link_list_prot_mm = link_list_alternate
	end
	--if less than 5 don't create collapsible list
	if table.getn(link_list_prot_mm) < 6 then
		refseq_prot_mm_collapse = "none"
		if refseq_prot_mm_default == nil and table.getn(link_list_prot_mm) == 0 then refseq_prot_mm_link = localNotApplicableStr end
	else
		refseq_prot_mm_collapse = "collapsible collapsed"
		refseq_prot_mm_default = table.remove .. ''--get first 5 elements in table and use for display
	end
	if link_list_prot_mm[#link_list_prot_mm] then
		refseq_prot_mm_link = table.concat
	end

	local locTitle = "위치(UCSC)" -- *lclz*
	local gstart_mb = p.locToMb
	local gend_mb = p.locToMb
	local chr_loc_link = ""
	if (string.match and string.match and string.match and string.match )then
		local chr_ucsc
		if chr == "MT" then
			chr_ucsc = "M" --UCSC uses "M" (not "MT") in URL for mitochondrial DNA
		else
			chr_ucsc = chr
		end
		chr_loc_link = "[https://genome.ucsc.edu/cgi-bin/hgTracks?org=Human&db="..db.."&position=chr"..chr_ucsc..":"..gstart.."-"..gend.." ".."Chr "..chr_ucsc..": "..gstart_mb.." – "..gend_mb.." Mb]"
	else
		chr_loc_link = localNotApplicableStr
	end
	local gstart_mm_mb = p.locToMb
	local gend_mm_mb = p.locToMb
	local chr_loc_mm_link = ""
	if (string.match and string.match and string.match and string.match )then
		local chr_mm_ucsc
		if chr_mm == "MT" then
			chr_mm_ucsc = "M" --UCSC uses "M" (not "MT") in URL for mitochondrial DNA
		else
			chr_mm_ucsc = chr_mm
		end
		chr_loc_mm_link = "[https://genome.ucsc.edu/cgi-bin/hgTracks?org=Mouse&db="..db_mm.."&position=chr"..chr_mm_ucsc..":"..gstart_mm.."-"..gend_mm.." ".."Chr "..chr_mm_ucsc..": "..gstart_mm_mb.." – "..gend_mm_mb.." Mb]"
	else
		chr_loc_mm_link = localNotApplicableStr
	end

	local pubmedTitle = "PubMed 검색" -- *lclz*
	local pubmed_link = entrez_gene
	if string.match and entrez_gene ~= localNotApplicableStr then
		pubmed_link = frame:extensionTag--expandTemplate creates cite web template 
	end
	local pubmed_mm_link = entrez_gene_mm
	if string.match and entrez_gene_mm ~= localNotApplicableStr then
		pubmed_mm_link = frame:extensionTag--expandTemplate creates cite web template 
	end

	root
end

function p.formatRow(title)
	root
end

function p.renderFooter
	local text = "위키데이터" --**lclz**
	local hs_link = "인간 보기/편집" --**lclz**
	local mm_link = ""
	local link_no_hs
	local link_no_mm

	if Qid_mm == "" then
		link_no_mm = 0
		link_no_hs = 4
	else
		link_no_mm = 2
		link_no_hs = 2
		mm_link = "쥐 보기/편집" --**lclz**
	end

	root
	root:done --end root table
end

--this code isn't used was hoping could do some generalization of rows
function p.rowLabel(label)
	root
			--:done
end

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

	local f = {'labels','en','value'} --**lclz**

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

		data = data[index] or data[tonumber(index)]
		if not data then
			return
		end

		i = i + 1
	end
end

-- Get property values formatted as a string of a given instance/entity.
-- 'entity' parameter denfines the instance from which we want to get some property values.
-- 'propertyID' parameter defines from which property the values are gotten.
-- 'rertun_val' parameter, if no result is returned, the value assigned to this parameter is returned, the default value is an empty string.
-- 'sep' parameter is the separation caracter used to separate returned values , default is a space caracter, e.g. ' '.
-- Assign to 'stated_in' a wikidata entry id, if getValue should only return values containing a reference statement 'stated in' . Note that the 'stated_in' parameter is only considered, if the assigned value to 'propertyID' is a wikidata entry.
function p.getValue

	local claims
	if return_val == nil then return_val = "" end
	if sep == nil then sep = " " 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 = {}
			for k, v in pairs(claims) do
				local datav = mw.wikibase.label(v.mainsnak.datavalue.value["id"])
				if datav == nil then datav = " " end
				--Filter statements with the specified stated_in reference value, if none (stated_in = nil) all statements are considered.
				local is_from_given_source = true
				if stated_in ~= nil then
					is_from_given_source = false
					if v.references then
						for rk, rv in pairs(v.references) do
							local ref_val = rv.snaks.P248
							if ref_val then
								for stated_k, stated_v in pairs(ref_val) do
									if (stated_v and stated_v.snaktype == "value" and stated_v.datavalue.type == "wikibase-entityid") then
										local ref_stated_in_val = stated_v.datavalue.value["id"]
										if ref_stated_in_val == stated_in then is_from_given_source = true end
									end
								end
							end
						end
					end
				end
				if is_from_given_source then
					out[#out + 1] = datav
				end
			end
			return table.concat
		else
		-- just return best values
			return entity:formatPropertyValues(propertyID).value
		end
	else
		return return_val
	end
end

function p.getValueProtein
	if return_val == nil then return_val = "" end
	local sep = ","
	local overall_results = {} --should return empty if nothing assigned
	for key, val in pairs(protein_entities) do --in cases where there are multiple encodes we loop through each and return concatenated data as a whole
		local claims
		local entity = val --each protein in encodes
		if entity and entity.claims then
			claims = entity.claims[propertyID]
		end
		if claims then
			local results
			-- 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.getLabel("Q" .. v.mainsnak.datavalue.value["numeric-id"])
					if datav == nil then datav = " " end
					out[#out + 1] = datav
				end
				results = table.concat
			else
				results = entity:formatPropertyValues(propertyID).value
			end
			overall_results[#overall_results+1] = results --individual propertyID value stored in this index
		end
	end

	local str_overall_results = table.concat --weirdness happens when add a sep = " " otherwise each value represented one time
	if string.match then
		return str_overall_results
	else
		return return_val
	end
end

--general function to get value given an entity and property
function p.getQid(entity)
	local Qid
	if entity and entity.id then
		Qid = entity.id
		return Qid
	else
		return ""
	end
end

--get random value that is preferred ranked
-- *lclz*: Sometimes Wikibase returns punctuations other than "," depending on
-- your site's language. Consider adding a gsub here.
function p.getRefseq_mRNA
	if return_val == nil then return_val = "" end
	local input_rank = "RANK_PREFERRED" ---this is mostly like won't do anything because ranking isn't maintained in wikidata
	local claims

	if 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 sitelink = mw.wikibase.getSitelink("Q" .. v.mainsnak.datavalue.value["numeric-id"])
				local label = mw.wikibase.getLabel("Q" .. v.mainsnak.datavalue.value["numeric-id"])
				if label == nil then label = "Q" .. v.mainsnak.datavalue.value["numeric-id"] end

				if sitelink then
					out[#out + 1] = "" .. label .. ""
				else
					out[#out + 1] = "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]"
				end
			end
			return table.concat
		else
			local results = entity:formatPropertyValues.value

			--loop through results until get a NP or NM or just return whatever is in first element
			--[[local results_split = mw.text.split

			local preffered_results = " "
			if results_split[1] then
				preferred_result = mw.text.trim(results_split[1]) --return first element if desired prefix not found and remove whitespace
			end
			local id --refseq id in question
			for i, id in ipairs(results_split) do
				local trim_id = mw.text.trim(id)
				if string.match then
					preferred_result = trim_id --overwrite each time found only need one to display
				end
			end
			if preferred_result then
				return preferred_result --return a id starting with NP or NM
			else
				return return_val --return first element because desired prefix not found and remove whitespaces
			end
			--]]
			return results
		end
	else
		return return_val
	end
end

-- *lclz*: same as getRefseq_mRNA
function p.getRefseq_protein
local sep = localSeparatorStr
local overall_results = {} --should return empty if nothing assigned

	for key, val in pairs(protein_entities) do --in cases where there are multiple encodes we loop through each and return concatenated data as a whole

		local claims
		local entity = val --each protein in encodes
		if entity.claims then
			claims = entity.claims[propertyID]
		end
		if claims then
			local results
			-- 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.getLabel("Q" .. v.mainsnak.datavalue.value["numeric-id"])
					if datav == nil then datav = " " end
					out[#out + 1] = datav
				end
				results = table.concat
			else
				results = entity:formatPropertyValues.value
			end
			overall_results[#overall_results+1] = results --a list is in each index
		end

	end
	--why are there duplicate results here
	local str_overall_results = table.concat
	return str_overall_results

end
	--[[
	local results_split = mw.text.split --split complete list so can loop through..probably a more direct way to do this
				--loop through results until get a NP or NM or just return whatever is in first element

	local preffered_result = results_split[1] or ""

	for i, id in ipairs(results_split) do
		local trim_id = mw.text.trim(id)
		--check of id starts with NP or NM
		if string.match then
			preferred_result = trim_id --overwrite each time found only need one to display
		end
	end
	--check if something in preffered_result if not get first element in result_split
	if p.isempty(preffered_result) then
		return return_val
	else
		return preferred_result --return a id starting with NP or NM
	end

end --]]

--gets an image
function p.getImage

	local claims

	if entity and entity.claims then
		claims = entity.claims[propertyID]
	end

	if claims then
		if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then
			local out = {}
			for k, v in pairs(claims) do
				local filename = v.mainsnak.datavalue.value
				out[#out + 1] = "" .. imgsize .. ""
			end
				return table.concat
		else
			return ""
		end
	else
		return ""
	end
end

function p.getPDB(protein_entities)
	local pdb_propertyID = "P638"
	local overall_results = {}
	for key, val in pairs(protein_entities) do --in cases where there are multiple encodes we loop through each and return concatenated data as a whole
		local claims
		local entity = val
		if entity and entity.claims then
			claims = entity.claims[pdb_propertyID]
		end
		local sitelink = "https://www.rcsb.org/structure/"
		if claims then
			local results
			if (claims[1] and claims[1].mainsnak.snaktype == "value") then

				local out = {}
				for k, v in pairs(claims) do
					local label = mw.wikibase.getLabel(v.mainsnak.datavalue.value)
					if label == nil then label = v.mainsnak.datavalue.value end

					if sitelink then
						out[#out + 1] = "[" .. sitelink .. label .. " " ..label .. "]"
					else
						out[#out + 1] = "" .. label .. ""
					end
				end
				results = table.concat -- *lclz*: punctuation 
			else
				results = entity:formatPropertyValues.value
			end
			overall_results[#overall_results+1] = results --individual propertyID values stored in this index
		end
	end
	return table.concat
end

function p.getAliases(entity)
	if entity['aliases'] ~= nil then
		-- *lclz*: You will need a different language here.
		-- If you are aiming for an "en" fallback, consider a set data structure.

		-- zhwp went a bit further here: they moved this call after "gene_symbol",
		-- so that this function can perform the deduplication here instead of
		-- in renderIdentifiers. That way they skip messing with commas and spaces.
		local test = entity['aliases']['en']
		if test then
			local a = ''
			for key, value in ipairs(test) do
				a = a .. ', ' .. value['value']
			end
			return a
		else
			return ""
		end
	else
		return ""
	end

end

--get a geneome start P644 or end P645
function p.getChromosomeLoc
	-- will contain the numeric value for the requested coordinate
	local output = ""
	local sep = " "
	-- can only be P644 (genomic start) or P645 (genomic end) for this to work
	-- should probably try to catch that. Might also increase legibility to use specific variable names when possible
--	local propertyID = mw.text.trim(frame.args[1] or "")
	-- this can really only be P659 right now. I'm not sure of the value of including it as a parameter as other values will likely break this function
	local qualifierID = "P659" --mw.text.trim(frame.args[2] or "")
	-- Why do we include this here? What should happen if FETCH_WIKIDATA is not included?
	--local input_parm = mw.text.trim(frame.args[3] or "")
	-- this can needs to be fed to the function either by a call to or by setting it directly (e.g. if the function was applied on a page other than the targeted gene)
	--alert if this id is not a valid thing in wikidata, a Lua error will occur that says
	--The ID entered is unknown to the system. Please use a valid entity ID.
	--local itemID = mw.text.trim(frame.args[4] or "")
	-- will track the different builds pulled from the qualifiers
	local newest_build = "0"
	-- starts the process
	--local entity = mw.wikibase.getEntity(itemID)
	local claims
	--gets a table of claims on the (genomic start or end) property Q19847637
	if entity and entity.claims then
		claims = entity.claims[propertyID]
	end
	--will return nothing if no claims are found
	if claims then
		--checking to be sure claims is populated, not sure it its needed
		if (claims[1] ) then
			--useful for debugging
			--local out = {}
			--pulls the genome location from the claim
			for k, v in pairs(claims) do
				local location = v.mainsnak.datavalue.value
				--debugging
				--out[#out + 1] = k.." location:" .. location.. " || "
				--gets the qualifiers linked to the current claim
				local quals
				if v.qualifiers then
					quals = v.qualifiers.P659
				end
				--if there are any
				if quals then
					for qk, qv in pairs(quals) do
						local qual_obj_id = "Q"..qv.datavalue.value["numeric-id"]
						--get to the entity targeted by the qualifier property. Genome builds are Items in wikidata
						local qual_obj = mw.wikibase.getEntity(qual_obj_id)
						local alias = ""
						--this uses the aliases to pull out version numbers
						--seems like there ought to be a better way to do this, but likely would need to change the data added by the bot
						if qual_obj["aliases"] ~= nil then
							local test = qual_obj["aliases"]["en"]
							for key, value in ipairs(test) do
								if string.match then
									alias = value['value']
									local build_no = alias:gsub
									--report only the most location associated with the most recent build
									--if there is more than one location per build, just give one back as that is not our problem right now.
									if build_no > newest_build then
										output = location
										newest_build = build_no
									end
								end
							end
						end
					end
				--in case there are no qualifiers, but there is a location, might as well return it
				else
					output = location
				end
			end
			return output
		else
			return ""
		end
	else
		return ""
		--debug
		--"no claims for "..itemID.." prop "..propertyID
	end
end

function p.getAliasFromGenomeAssembly
	-- will contain the numeric value for the requested coordinate
	local output = ""
	local sep = " "
	local propertyID = "P644" --genomic start used
	local qualifierID = "P659" --genomic assembly

	local newest_build = "0"
	local claims
	if entity.claims then
		claims = entity.claims[propertyID]
	end
	--will return nothing if no claims are found
	if claims then
		--checking to be sure claims is populated, not sure it its needed
		if (claims[1] ) then
			--useful for debugging
			--local out = {}
			--pulls the genome location from the claim
			for k, v in pairs(claims) do
				local location = '' -- TODO what should this be? defining location is required for 'output = location' below
				local quals
				if v.qualifiers then
					quals = v.qualifiers.P659
				end
				--if there are any
				--as of Aug. 2017, P659-genomic assembly is stored only in human genomic data. GRCh38 (newer) or GRCh37(older).
				--Mouse genomic data doesn't have P659-genomic assembly data. But mouse has only one version. GRCm38/mm10.
				if quals then
					for qk, qv in pairs(quals) do
						local qual_obj_id = "Q"..qv.datavalue.value["numeric-id"]
						--get to the entity targeted by the qualifier property. Genome builds are Items in wikidata
						local qual_obj = mw.wikibase.getEntity(qual_obj_id)
						local alias = ""
						--this uses the aliases to pull out version numbers
						--seems like there ought to be a better way to do this, but likely would need to change the data added by the bot
						if qual_obj["aliases"] ~= nil then
							local test = qual_obj["aliases"]["en"]
							for key, value in ipairs(test) do
								if string.match then
									alias = value['value']
									local build_no = alias:gsub
									--For example, prefix is "hg" (this is set when the function was called),
									--alias is "hg38" (which is data stored in Wikidata). Then "build_no" becomes "38".
									--report only the most location associated with the most recent build
									--if there is more than one location per build, just give one back as that is not our problem right now.
									if build_no > newest_build then
										newest_build = build_no
									end
								end
							end
						end
					end
				--in case there are no qualifiers, but there is a location, might as well return it
				else
					output = location
				end
			end
			return prefix .. newest_build
		else
			return ""
		end
	else
		return ""
	end
end

-- *lclz*: Your language's wikidata may have different nouns for chromosome and
-- mitochodria.
function p.trimChromosome(entity)
	local string_to_trim = p.getValue
	local out = ''

	--"mitochondrion" and "chromosome MT" is used for mitochondrial DNA.
	--See d:Special:WhatLinksHere/Q18694495
	if string.find or string.find or string.find or string.find then --match both 'mitochondrio'/'mitochondrial'
		out = "MT"
	elseif string.find or string.find then --**lclz** Add your local label, otherwise it may break
		out = string.match--extract number from string
		if out == nil then
			out = string.match or string.match
		end
	end
	return out
end

function p.locToMb
	num = tonumber(num)
	if num == nil then
		return ""
	else
		local mb = num/1000000
		local mult = 10^(idp or 0)
		return math.floor(mb * mult + 0.5) / mult
	end
end

function p.isempty(s)
	return s == nil or s == ''
end

function p.getGO
	--propertyID ie molecular, cellular, function

	local overall_results = {}
	local results = "" --string to return

	for key, val in pairs(protein_entities) do

		local claims
		local entity = val
		if entity.claims then
			claims = entity.claims[propertyID] -- ie molecular, cellular, function
		end
		local propertyID_child = "P686" -- Gene Ontology ID

		if claims then

			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 itemID_child = "Q" .. v.mainsnak.datavalue.value["numeric-id"] --get Qid of property item so can get the GOid
					local entity = mw.wikibase.getEntity(itemID_child)
					local claims
					local result_GOID = ''
					if entity and entity.claims then claims = entity.claims[propertyID_child] end
					if claims then
						result_GOID = entity:formatPropertyValues.value
					else
						result_GOID = nil --no GO ID
					end
					local sitelink = "http://amigo.geneontology.org/amigo/term/"
					local label = mw.wikibase.getLabel("Q" .. v.mainsnak.datavalue.value["numeric-id"])
					if label == nil then label = "Q" .. v.mainsnak.datavalue.value["numeric-id"] end
					local wiki_link = ""
					if sitelink and result_GOID ~= nil then
						wiki_link = "\n* [" .. sitelink .. result_GOID .. " " .. label .."]"
					else
						wiki_link = "\n* [[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]"
					end
					overall_results[#overall_results+1] = wiki_link
				end

			else
				results = entity:formatPropertyValues.value
			end

		end
		--overall_results[#overall_results+1] = results --each protein GO terms stored in this index, so table contains all the GO terms with duplicates
	end

	local hash = {} --temp check
	local res = {} --no dups

	for _,v in ipairs(overall_results) do
		if (not hash[v]) then
			res[#res+1] = v
			hash[v] = true
		end
	end
	return table.concat
end

local function getReference
	local f = {"claims",property_id, ref_index, "references"}
	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
			else
				return tostring(data)
			end
		end

		data = data[index] or data[tonumber(index)]
		if not data then
			return ""
		end
		i = i + 1
	end
end

function p.getDisease
	local claims
	local return_val = "" -- define variable; this line was 'if return_val == nil then return_val = "" end' which looks like a copy/paste
	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 = {}
			--
			--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.getLabel("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.getSitelink(id)
				local refLink = ""
				local ref = ""
				ref = getReference
				if (ref ~= nil and ref ~= '') then
					--refLink = refLink..","..ref
					refLink = ref
				end

				--if refLink = "" then --skip if there isn't a reference found

				if linkTarget then
					out[#out + 1] = ""..datav..""
				else
					out[#out + 1] = "" .. datav .. ""
				end
				datasource[#out] = refLink
				--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

function p.getDrug
	local out = {}
	local datasource = {}
	local pname = {}
	local pqid = {}

	for key, val in pairs(protein_entities) do
		local claims
		local entity = val
		local name = check_values
		if entity.claims then
			claims = entity.claims[propertyID] -- ie physically interacts with
		end
		local protein_id
		if entity then protein_id = entity.id else protein_id = "" 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 datav = mw.wikibase.getLabel("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.getSitelink(id)
					local refLink = ""
					local ref = getReference --just check if anything returned
					if (ref ~= nil and ref ~= '') then
						refLink = ref
					end
					if linkTarget then
						out[#out + 1] = ""..datav..""
					else
						out[#out + 1] = "" .. datav .. ""
					end
					pname[protein_id] = name
					pqid[#out] = protein_id
					datasource[#out] = refLink
				end --end k,v claims loop
			end --end claims[1]
		end --if claims
	end -- end protein_entities loop
	return out, datasource, pqid, pname
end

function p.separateWithComma(bp)
	--Separate number with comma. For example when this function gets "12345678", returns "12,345,678"
	local commaSeparated = bp
	while true do
		local k
		commaSeparated, k = string.gsub(commaSeparated, "^(-?%d+)(%d%d%d)", '%1,%2')
		if k == 0 then
			break
		end
	end
	return commaSeparated
end