Module:GHS phrases

From MOASSpedia
Jump to navigation Jump to search

List all H phrases

Code Phrase
H200 Unstable explosive
H201 Explosive: mass explosion hazard
H202 Explosive: severe projection hazard
H203 Explosive: fire, blast or projection hazard
H204 Fire or projection hazard
H205 May mass explode in fire
H206 Fire, blast or projection hazard: increased risk of explosion if desensitizing agent is reduced
H207 Fire or projection hazard; increased risk of explosion if desensitizing agent is reduced
H208 Fire hazard; increased risk of explosion if desensitizing agent is reduced
H209 Explosive
H210 Very explosive
H211 May be sensitive
H220 Extremely flammable gas
H221 Flammable gas
H222 Extremely flammable material
H223 Flammable material
H224 Extremely flammable liquid and vapour
H225 Highly flammable liquid and vapour
H226 Flammable liquid and vapour
H227 Combustible liquid
H228 Flammable solid
H230 May react explosively even in the absence of air
H231 May react explosively even in the absence of air at elevated pressure and/or temperature
H240 Heating may cause an explosion
H241 Heating may cause a fire or explosion
H242 Heating may cause a fire
H250 Catches fire spontaneously if exposed to air
H251 Self-heating: may catch fire
H252 Self-heating in large quantities: may catch fire
H260 In contact with water releases flammable gases which may ignite spontaneously
H261 In contact with water releases flammable gas
H270 May cause or intensify fire: oxidizer
H271 May cause fire or explosion: strong oxidizer
H272 May intensify fire: oxidizer
H280 Contains gas under pressure: may explode if heated
H281 Contains refrigerated gas: may cause cryogenic burns or injury
H282 Extremely flammable chemical under pressure: May explode if heated
H283 Flammable chemical under pressure: May explode if heated
H284 Chemical under pressure: May explode if heated
H290 May be corrosive to metals
H300 Fatal if swallowed
H300+H310 Fatal if swallowed or in contact with skin
H300+H310+H330 Fatal if swallowed, in contact with skin or if inhaled
H300+H330 Fatal if swallowed or if inhaled
H301 Toxic if swallowed
H301+H311 Toxic if swallowed or in contact with skin
H301+H311+H331 Toxic if swallowed, in contact with skin or if inhaled
H301+H331 Toxic if swallowed or if inhaled
H302 Harmful if swallowed
H302+H312 Harmful if swallowed or in contact with skin
H302+H312+H332 Harmful if swallowed, in contact with skin or if inhaled
H302+H332 Harmful if swallowed or inhaled
H303 May be harmful if swallowed
H303+H313 May be harmful if swallowed or in contact with skin
H303+H313+H333 May be harmful if swallowed, in contact with skin or if inhaled
H303+H333 May be harmful if swallowed or if inhaled
H304 May be fatal if swallowed and enters airways
H305 May be harmful if swallowed and enters airways
H310 Fatal in contact with skin
H310+H330 Fatal in contact with skin or if inhaled
H311 Toxic in contact with skin
H311+H331 Toxic in contact with skin or if inhaled
H312 Harmful in contact with skin
H312+H332 Harmful in contact with skin or if inhaled
H313 May be harmful in contact with skin
H313+H333 May be harmful in contact with skin or if inhaled
H314 Causes severe skin burns and eye damage
H315 Causes skin irritation
H315+H320 Causes skin and eye irritation
H316 Causes mild skin irritation
H317 May cause an allergic skin reaction
H318 Causes serious eye damage
H319 Causes serious eye irritation
H320 Causes eye irritation
H330 Fatal if inhaled
H331 Toxic if inhaled
H332 Harmful if inhaled
H333 May be harmful if inhaled
H334 May cause allergy or asthma symptoms of breathing difficulties if inhaled
H335 May cause respiratory irritation
H336 May cause drowsiness or dizziness
H340 May cause genetic defects
H341 Suspected of causing genetic defects
H350 May cause cancer
H350i May cause cancer by inhalation
H351 Suspected of causing cancer
H360 May damage fertility or the unborn child
H360D May damage the unborn child
H360Df May damage the unborn child. Suspected of damaging fertility.
H360F May damage fertility
H360FD May damage fertility. May damage the unborn child.
H360Fd May damage fertility. Suspected of damaging the unborn child.
H361 Suspected of damaging fertility or the unborn child
H361d Suspected of damaging the unborn child
H361f Suspected of damaging fertility
H361fd Suspected of damaging fertility. Suspected of damaging the unborn child.
H362 May cause harm to breast-fed children
H370 Causes damage to organs
H371 May cause damage to organs
H372 Causes damage to organs through prolonged or repeated exposure
H373 May cause damage to organs through prolonged or repeated exposure
H400 Very toxic to aquatic life
H401 Toxic to aquatic life
H402 Harmful to aquatic life
H410 Very toxic to aquatic life with long lasting effects
H411 Toxic to aquatic life with long lasting effects
H412 Harmful to aquatic life with long lasting effects
H413 May cause long lasting harmful effects to aquatic life
H420 Harms public health and the environment by destroying ozone in the upper atmosphere
H441 Very toxic to terrestrial invertebrates

List all P phrases

Code Phrase
P102 Keep out of reach of children.
P103 Read label before use.
P201 Obtain special instructions before use.
P202 Do not handle until all safety precautions have been read and understood.
P210 Keep away from heat, hot surfaces, sparks, open flames and other ignition sources. No smoking.
P211 Do not spray on an open flame or other ignition source.
P212 Avoid heating under confinement or reduction of the desensitized agent.
P220 Keep/Store away from clothing/.../combustible materials.
P221 Take any precaution to avoid mixing with combustibles.
P222 Do not allow contact with air.
P223 Do not allow contact with water.
P230 Keep wetted with ...
P231 Handle and store contents under inert gas/...
P231+P232 Handle and store contents under inert gas. Protect from moisture
P232 Protect from moisture.
P233 Keep container tightly closed.
P234 Keep only in original container/packaging.
P235 Keep cool.
P235+P410 Keep cool. Protect from sunlight.
P240 Ground and bond container and receiving equipment.
P241 Use explosion-proof electrical/ventilating/light/.../equipment.
P242 Use only non-sparking tools.
P243 Take action to prevent static discharges.
P244 Keep valves and fittings free from grease and oil
P250 Do not subject to grinding/shock/.../friction.
P251 Pressurized container – Do not pierce or burn, even after use.
P260 Do not breathe dust/fume/gas/mist/vapours/spray.
P261 Avoid breathing dust/fume/gas/mist/vapours/spray.
P262 Do not get in eyes, on skin, or on clothing.
P263 Avoid contact during pregnancy and while nursing.
P264 Wash ... thoroughly after handling.
P270 Do not eat, drink or smoke when using this product.
P271 Use only outdoors or in a well-ventilated area.
P272 Contaminated work clothing should not be allowed out of the workplace.
P273 Avoid release to the environment.
P280 Wear protective gloves/protective clothing/eye protection/face protection.
P281 Use personal protective equipment as required.
P282 Wear cold insulating gloves and either face shield or eye protection.
P283 Wear fire resistant or flame retardant clothing.
P284 Wear respiratory protection.
P285 In case of inadequate ventilation wear respiratory protection.
P301 IF SWALLOWED:
P301+P310 IF SWALLOWED: Immediately call a POISON CENTER or doctor/physician.
P301+P310+P330 IF SWALLOWED: Immediately call a POISON CENTER or doctor/physician. Rinse mouth.
P301+P312 IF SWALLOWED: Call a POISON CENTER or doctor/physician if you feel unwell.
P301+P312+P330 IF SWALLOWED: Call a POISON CENTER or doctor/physician if you feel unwell. Rinse mouth.
P301+P330+P331 IF SWALLOWED: Rinse mouth. Do NOT induce vomiting.
P302 IF ON SKIN:
P302+P312 IF ON SKIN: Call a POISON CENTER or doctor/physician if you feel unwell.
P302+P334 IF ON SKIN: Immerse in cool water or wrap in wet bandages.
P302+P335+P334 IF ON SKIN: Brush off loose particles from skin. Immerse in cool water or wrap in wet bandages.
P302+P350 IF ON SKIN: Gently wash with soap and water.
P302+P352 IF ON SKIN: Wash with soap and water.
P302+P352+P312 IF ON SKIN: Wash with soap and water. Call a POISON CENTER or doctor/physician if you feel unwell.
P302+P353 IF ON SKIN: Rinse skin with water [or shower].
P303 IF ON SKIN (or hair):
P303+P361+P353 IF ON SKIN (or hair): Remove/Take off immediately all contaminated clothing. Rinse skin with water [or shower].
P303+P361+P353+P315 IF ON SKIN (or hair): Remove/Take off immediately all contaminated clothing. Rinse skin with water [or shower]. Get immediate medical advice/attention.
P304 IF INHALED:
P304+P312 IF INHALED: Call a POISON CENTER or doctor/physician if you feel unwell.
P304+P340 IF INHALED: Remove victim to fresh air and keep at rest in a position comfortable for breathing.
P304+P340+P310 IF INHALED: Remove victim to fresh air and keep at rest in a position comfortable for breathing. Immediately call a POISON CENTER or doctor/physician.
P304+P340+P311 IF INHALED: Remove victim to fresh air and keep at rest in a position comfortable for breathing. Call a POISON CENTER or doctor/physician.
P304+P340+P312 IF INHALED: Remove victim to fresh air and keep at rest in a position comfortable for breathing. Call a POISON CENTER or doctor/physician if you feel unwell.
P304+P340+P315 IF INHALED: Remove victim to fresh air and keep at rest in a position comfortable for breathing. Get immediate medical advice/attention.
P304+P341 IF INHALED: If breathing is difficult, remove victim to fresh air and keep at rest in a position comfortable for breathing.
P305 IF IN EYES:
P305+P351+P338 IF IN EYES: Rinse continuously with water for several minutes. Remove contact lenses if present and easy to do. Continue rinsing.
P305+P351+P338+P310 IF IN EYES: Rinse continuously with water for several minutes. Remove contact lenses if present and easy to do. Continue rinsing. Immediately call a POISON CENTER or doctor/physician.
P305+P351+P338+P315 IF IN EYES: Rinse cautiously with water for several minutes. Remove contact lenses if present and easy to do. Continue rinsing. Get immediate medical advice/attention.
P306 IF ON CLOTHING:
P306+P360 IF ON CLOTHING: Rinse immediately contaminated clothing and skin with plenty of water before removing clothes.
P307 IF exposed:
P307+P311 IF exposed: Call a POISON CENTER or doctor/physician.
P308 IF exposed or concerned:
P308+P310 IF exposed or concerned: Immediately call a POISON CENTER or doctor/physician.
P308+P311 IF exposed or concerned: Call a POISON CENTER or doctor/physician.
P308+P313 IF exposed or concerned: Get medical advice/attention.
P309 IF exposed or you feel unwell:
P309+P311 IF exposed or you feel unwell: Call a POISON CENTER or doctor/physician.
P310 Immediately call a POISON CENTER or doctor/physician.
P311 Call a POISON CENTER or doctor/physician.
P312 Call a POISON CENTER or doctor/physician if you feel unwell.
P313 Get medical advice/attention.
P314 Get Medical advice/attention if you feel unwell.
P315 Get immediate medical advice/attention.
P320 Specific treatment is urgent (see ... on this label).
P321 Specific treatment (see ... on this label).
P322 Specific measures (see ... on this label).
P330 Rinse mouth.
P331 Do NOT induce vomiting.
P332 If skin irritation occurs:
P332+P313 If skin irritation occurs: Get medical advice/attention.
P333 If skin irritation or a rash occurs:
P333+P313 If skin irritation or a rash occurs: Get medical advice/attention.
P334 Immerse in cool water [or wrap in wet bandages].
P335 Brush off loose particles from skin.
P335+P334 Brush off loose particles from skin. Immerse in cool water/wrap in wet bandages.
P336 Thaw frosted parts with lukewarm water. Do not rub affected areas.
P336+P315 Thaw frosted parts with lukewarm water. Do not rub affected area. Get immediate medical advice/attention.
P337 If eye irritation persists:
P337+P313 Get medical advice/attention.
P338 Remove contact lenses if present and easy to do. Continue rinsing.
P340 Remove victim to fresh air and keep at rest in a position comfortable for breathing.
P341 If breathing is difficult, remove victim to fresh air and keep at rest in a position comfortable for breathing.
P342 If experiencing respiratory symptoms:
P342+P311 If experiencing respiratory symptoms: Call a POISON CENTER or doctor/physician.
P350 Gently wash with soap and water.
P351 Rinse cautiously with water for several minutes.
P352 Wash with plenty of water.
P353 Rinse skin with water [or shower].
P360 Rinse immediately contaminated clothing and skin with plenty of water before removing clothes.
P361 Remove/Take off immediately all contaminated clothing.
P361+P364 Take off immediately all contaminated clothing and wash it before reuse.
P362 Take off contaminated clothing.
P362+P364 Take off contaminated clothing and wash it before reuse.
P363 Wash contaminated clothing before reuse.
P364 And wash it before reuse.
P370 In case of fire:
P370+P372+P380+P373 In case of fire: Explosion risk. Evacuate area. DO NOT fight fire when fire reaches explosives.
P370+P376 In case of fire: Stop leak if safe to do so.
P370+P378 In case of fire: Use ... to extinguish.
P370+P380 In case of fire: Evacuate area.
P370+P380+P375 In case of fire: Evacuate area. Fight fire remotely due to the risk of explosion.
P370+P380+P375+P378 In case of fire: Evacuate area. Fight fire remotely due to the risk of explosion. Use ... to extinguish.
P371 In case of major fire and large quantities:
P371+P380+P375 In case of major fire and large quantities: Evacuate area. Fight fire remotely due to the risk of explosion.
P372 Explosion risk.
P373 DO NOT fight fire when fire reaches explosives.
P374 Fight fire with normal precautions from a reasonable distance.
P375 Fight fire remotely due to the risk of explosion.
P376 Stop leak if safe to do so.
P377 Leaking gas fire – do not extinguish unless leak can be stopped safely.
P378 Use ... to extinguish.
P380 Evacuate area.
P381 In case of leakage, eliminate all ignition sources.
P390 Absorb spillage to prevent material damage.
P391 Collect spillage.
P401 Store in accordance with ...
P402 Store in a dry place.
P402+P404 Store in a dry place. Store in a closed container.
P403 Store in a well ventilated place.
P403+P233 Store in a well ventilated place. Keep container tightly closed.
P403+P235 Store in a well ventilated place. Keep cool.
P404 Store in a closed container.
P405 Store locked up.
P406 Store in a corrosive resistant/... container with a resistant inner liner.
P407 Maintain air gap between stacks or pallets.
P410 Protect from sunlight.
P410+P403 Protect from sunlight. Store in a well ventilated place.
P410+P412 Protect from sunlight. Do not expose to temperatures exceeding 50 ºC/122 ºF.
P411 Store at temperatures not exceeding ... ºC/... ºF.
P411+P235 Store at temperatures not exceeding ... ºC/... ºF. Keep cool.
P412 Do not expose to temperatures exceeding 50 ºC/122 ºF.
P413 Store bulk masses greater than ... kg/... lbs at temperatures not exceeding ... °C/... °F.
P420 Store separately/away from other materials.
P422 Store contents under ...
P501 Dispose of contents/container to ...
P502 Refer to manufacturer or supplier for information on recovery or recycling.

List formats

|listtype=abbr (default)
P201, P302+P334, P502
Listtype options
|format=inline
P201: "Obtain special instructions before use.", P302+P334: "IF ON SKIN: Immerse in cool water or wrap in wet bandages.", P502: "Refer to manufacturer or supplier for information on recovery or recycling."
|format=bulleted
  • P201: Obtain special instructions before use.
  • P302+P334: IF ON SKIN: Immerse in cool water or wrap in wet bandages.
  • P502: Refer to manufacturer or supplier for information on recovery or recycling.
|format=unbulleted
  • P201: Obtain special instructions before use.
  • P302+P334: IF ON SKIN: Immerse in cool water or wrap in wet bandages.
  • P502: Refer to manufacturer or supplier for information on recovery or recycling.
|format=horizontal
  • P201: Obtain special instructions before use.
  • P302+P334: IF ON SKIN: Immerse in cool water or wrap in wet bandages.
  • P502: Refer to manufacturer or supplier for information on recovery or recycling.
|format=ordered
  1. P201: Obtain special instructions before use.
  2. P302+P334: IF ON SKIN: Immerse in cool water or wrap in wet bandages.
  3. P502: Refer to manufacturer or supplier for information on recovery or recycling.
|format=horizontal_ordered
  1. P201: Obtain special instructions before use.
  2. P302+P334: IF ON SKIN: Immerse in cool water or wrap in wet bandages.
  3. P502: Refer to manufacturer or supplier for information on recovery or recycling.

Full abbr list

Complete H, P lists (H200, H201, H202, ...)

As of 27 November 2021:

  • GHS H-phrases (110) H200, H201, H202, H203, H204, H205, H206, H207, H208, H209, H210, H211, H220, H221, H222, H223, H224, H225, H226, H227, H228, H230, H231, H240, H241, H242, H250, H251, H252, H260, H261, H270, H271, H272, H280, H281, H282, H283, H284, H290, H300, H300+H310, H300+H310+H330, H300+H330, H301, H301+H311, H301+H311+H331, H301+H331, H302, H302+H312, H302+H312+H332, H302+H332, H303, H303+H313, H303+H313+H333, H303+H333, H304, H305, H310, H310+H330, H311, H311+H331, H312, H312+H332, H313, H313+H333, H314, H315, H315+H320, H316, H317, H318, H319, H320, H330, H331, H332, H333, H334, H335, H336, H340, H341, H350, H350i, H351, H360, H360D, H360Df, H360F, H360FD, H360Fd, H361, H361d, H361f, H361fd, H362, H370, H371, H372, H373, H400, H401, H402, H410, H411, H412, H413, H420, H441
Order entered: |H201|H200| to check sorting.
  • GHS P-phrases (160) P102, P103, P201, P202, P210, P211, P212, P220, P221, P222, P223, P230, P231, P231+P232, P232, P233, P234, P235, P235+P410, P240, P241, P242, P243, P244, P250, P251, P260, P261, P262, P263, P264, P270, P271, P272, P273, P280, P281, P282, P283, P284, P285, P301, P301+P310, P301+P310+P330, P301+P312, P301+P312+P330, P301+P330+P331, P302, P302+P312, P302+P334, P302+P335+P334, P302+P350, P302+P352, P302+P352+P312, P302+P353, P303, P303+P361+P353, P303+P361+P353+P315, P304, P304+P312, P304+P340, P304+P340+P310, P304+P340+P311, P304+P340+P312, P304+P340+P315, P304+P341, P305, P305+P351+P338, P305+P351+P338+P310, P305+P351+P338+P315, P306, P306+P360, P307, P307+P311, P308, P308+P310, P308+P311, P308+P313, P309, P309+P311, P310, P311, P312, P313, P314, P315, P320, P321, P322, P330, P331, P332, P332+P313, P333, P333+P313, P334, P335, P335+P334, P336, P336+P315, P337, P337+P313, P338, P340, P341, P342, P342+P311, P350, P351, P352, P353, P360, P361, P361+P364, P362, P362+P364, P363, P364, P370, P370+P372+P380+P373, P370+P376, P370+P378, P370+P380, P370+P380+P375, P370+P380+P375+P378, P371, P371+P380+P375, P372, P373, P374, P375, P376, P377, P378, P380, P381, P390, P391, P401, P402, P402+P404, P403, P403+P233, P403+P235, P404, P405, P406, P407, P410, P410+P403, P410+P412, P411, P411+P235, P412, P413, P420, P422, P501, P502
Order entered: |P103|P102| to check sorting.

Features

Hide Doubles

Repeated phrase codes are hidden:

  • {{GHS phrases|H400|H401|H401|H401}}H400, H401

Omit Rules

|omit=true (default)
Omit Rules as applied by {{GHS phrases}} ()

Omit Rules: when the keep ID is present, do not show the omit ID phrase
• keep H314, omit H318
• keep P203, omit P103
• keep P413, omit P235
• keep H411, omit H401
• keep P411, omit P235
• keep H412, omit H402
• keep H410, omit H400
• keep P236, omit P234

  • Categorised as Category:GHS warnings (0) under "O"
  • Source: "Globally Harmonized System of Classification and Labelling of Chemicals" (pdf). 2021. Annex 3: Codification of Statements and Pictograms (pp 268–385).
  • {{GHS phrases|H314|H318}}H314

All module functions

module function template note
main {{GHS phrases}}
{{H-phrases}} {{P-phrases}}

|setid=H, P preset
listAll {{GHS phrases/inline}} equals main + |listtype=inline
numberOfPhrases {{GHS phrases/number of phrases}}
listAll {{GHS phrases/list all}}
listOmitRules {{GHS phrases/list omit rules}} documentation only; no |setid=

Tracking

See also

Lists: GHS hazard statements, GHS precautionary statements



  1. ^ a b "Globally Harmonized System of Classification and Labelling of Chemicals" (pdf). 2021. Annex 3: Codification of Statements and Pictograms (pp 268–385).
--------------------------------------------------------------------------------
-- Module:GHS phrases
-- 
-- main: reads GHS parameters (arguments like "H301", "P401")
--		and returns for each (listtype='abbr'):
--		phraseID visible; formal phrase text as <abbr title="...">
-- setID	= "H" or "P"
-- phraseID = e.g. "H201", "P231+P234"
-- phrase text read from array tables in [[Module:GHS phrases/data]]
--
-- Implements: [[Template:GHS phrases]]
-- Helppage: [[Template:GHS phrases]]
-- Error category: [[Category:GHS errors]], [[Category:GHS warnings]] (mainspace pages only)
--
-- Also: 
-- listAll(), numberOfPhrases(), listOmitRules(),
-- listtype, omit
--------------------------------------------------------------------------------
require('Module:No globals')
local r = {}	-- "r" for return, so no confusion with setID P
local GHSdata	= mw.loadData('Module:GHS phrases/data')
local getArgs	= require('Module:Arguments').getArgs
local tTools	= require('Module:TableTools')
local yesno		= require('Module:Yesno')
local tArgName	= {} -- named parameters (setid, omit, listtype)
local tMessagesToShow = {} -- the tail: Preview, Categories

--------------------------------------------------------------------------------
-- wlHelpPage
--
-- Formats page as [[Helppage#Section|Label]]
-- by default, sLabel == sSection
--------------------------------------------------------------------------------
local function wlHelpPage(sSection, sLabel)
local sHelpPage = 'Template:GHS phrases'
	
	if sLabel == nil then sLabel = sSection end
	
	if (sLabel or '') == '' then
		sLabel = ''
	else
		sLabel = '|' .. sLabel 
	end
	if (sSection or '') == '' then
		sSection = ''
	else
		sSection = '#' .. sSection
	end
	return '[[' .. sHelpPage .. sSection .. sLabel .. ']]'
end

--------------------------------------------------------------------------------
-- addErrorCategory
--
-- Formats as [[Category:GHS errors|catsort]]
-- or '' when in other namespace.
-- sCatsort option using: H, P, _
--------------------------------------------------------------------------------
local function addErrorCategory(sCatsort)
local pagetype = require('Module:Pagetype').main
	
	local wlErrCat = ''
	if pagetype() == 'article' then -- mainspace only
		if sCatsort == nil then sCatsort = tArgName['setID'] end
		
		if sCatsort == '' then
			wlErrCat = '[[Category:GHS errors]]'
		else
			wlErrCat = '[[Category:GHS errors|' .. sCatsort .. ']]'
		end
	else
		return ''
	end

	table.insert(tMessagesToShow, wlErrCat)
	return
end

--------------------------------------------------------------------------------
-- addWarningCategory
--
-- Formats as [[Category:GHS warnings|catsort]]
-- mainspace only, or '' when in other namespace.
-- sCatsort option using: H, P, U, ?, D, O
--------------------------------------------------------------------------------
local function addWarningCategory(sCatsort)
local pagetype = require('Module:Pagetype').main
if sCatsort == nil then sCatsort = tArgName['setID'] end
		
	local wlWarnCat = ''
	if pagetype() == 'article' then -- mainspace only
		if sCatsort == '' then
			wlWarnCat = '[[Category:GHS warnings]]'
		else
			wlWarnCat = '[[Category:GHS warnings|' .. sCatsort .. ']]'
		end
	else
		return 
	end

	table.insert(tMessagesToShow, wlWarnCat)
	return
end

--------------------------------------------------------------------------------
-- addPreviewMsg
--------------------------------------------------------------------------------
local function addPreviewMsg(sMsg)
local previewWarn = require('Module:If preview')._warning
	table.insert(tMessagesToShow, previewWarn({sMsg}))
	return
end

--------------------------------------------------------------------------------
-- showPreviewMsg
--
-- show table tMessagesToShow
-- preview-messages and errorcat
-- all namespaces
--------------------------------------------------------------------------------
local function showPreviewMsg()
	if tTools.size(tMessagesToShow) > 0 then
		return table.concat(tMessagesToShow, '')
	else
		return ''
	end
end

--------------------------------------------------------------------------------
-- applyRemoveDuplicates
--
-- returns edited table, with double Codes removed
-- adds warning with codes.
-- base table tArgs is walked through by a iwalker that reads a singel code,
-- then a ikiller checks the upward part of the same table to delete all copies
-- ikiller starts at end of table, walks towards iwalker; then tArgs is compressed
-- iwalker steps 1 up in the freshly compressed table
-- Used: iArgs is sorted, and order stays same. compress does not change that.
--------------------------------------------------------------------------------
local function applyRemoveDuplicates(tArgs)
local iR, iK -- iR = reader, iK = killer
local hit = false

	iR = 1
	while iR < #tArgs do
		iK = #tArgs -- will be counting downwards
		while iK > iR do
			if tArgs[iK] == tArgs[iR] then
				hit = true
				addPreviewMsg('Duplicate removed: ' .. tArgs[iR])
				table.remove(tArgs, iK)
				tTools.compressSparseArray(tArgs)
			end
			iK = iK - 1
		end
		tTools.compressSparseArray(tArgs)
		iR = iR + 1
	end

	if hit then
		addWarningCategory('D')
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- applyOmitRules
--
-- returns edited table, with Omit phraseID's removed
-- Omit rule is per GHS_Rev9E_0.pdf (2021)
--------------------------------------------------------------------------------
local function applyOmitRules(tArgs)
local tRules = GHSdata['tOmitRules']
	local hit = false
	
	for keep, omit in pairs(tRules) do
		if tTools.inArray(tArgs, omit) then
			if tTools.inArray(tArgs, keep) then
				hit = true
				for i, k in pairs(tArgs) do
					if k == omit then
						table.remove(tArgs, i)		
					end
				end
				addPreviewMsg(wlHelpPage('Omit Rules') .. ': keep ' .. keep .. ', omit ' .. omit)
			end
		end
	end
	if hit then
		tTools.compressSparseArray(tArgs)
		addWarningCategory('O')
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- label H-phrases or P-phrases
--------------------------------------------------------------------------------
local function PHlabel()
	if tArgName['setID'] == 'GHS' then
		return 'GHS phrases'
	else
		return tArgName['setID'] .. '-phrases'
	end
end

--------------------------------------------------------------------------------
-- inMono
--
-- Use mono font-family (from: Template:Mono)
--------------------------------------------------------------------------------
local function inMono(s)
	if s == nil then s = '' end
	return '<span class="monospaced" style="font-family: monospace;">' .. s .. '</span>'
end

--------------------------------------------------------------------------------
-- wlInlineTag
--
-- Returns <sup>[?]</sup> with wikilink to [[helppage#section|errormessage]]
--------------------------------------------------------------------------------
local function wlInlineTag(phraseID)
	local sMsg
	sMsg = '<sup><span class="noprint Inline-Template">&#91;<i>'
				.. wlHelpPage(PHlabel(), '<span title="' 
									.. PHlabel() .. ': '
									.. phraseID
									.. ' not found'
									.. '">?</span>')
				.. '</i>&#93;</span></sup>'
	return sMsg
end

--------------------------------------------------------------------------------
-- errorPhraseIDnotFound
--
-- Returns single value when error (not found in list):
-- plain value + inline warning [?] (linked) + error cat (mainsp) + preview warning
--------------------------------------------------------------------------------
local function errorPhraseIDnotFound(phraseID)
	if phraseID == nil then phraseID = '' end
	
	local inlineTag = wlInlineTag(phraseID)
	local previewMsg = wlHelpPage(PHlabel()) .. ': \"' .. phraseID .. '\" not found'
	addPreviewMsg(previewMsg)
	addErrorCategory()
	
	return phraseID .. inlineTag
end

--------------------------------------------------------------------------------
-- errorHPsetIDnotFound
--
-- setID H or P could not be found
--------------------------------------------------------------------------------
local function errorHPsetIDnotFound()
	local sMsg
	sMsg = wlHelpPage('', PHlabel())
			.. ': "H" or "P" set id not found' 
			.. ' (please use form like "|H200" or "|P300+P301")'
	addPreviewMsg(sMsg)
	addErrorCategory('?')
	return showPreviewMsg()
end

--------------------------------------------------------------------------------
-- errorHPsetIDmissing
--
-- parameter |setid= to be used
--------------------------------------------------------------------------------
local function errorHPsetIDmissing()
	local sMsg
	sMsg = wlHelpPage( '', PHlabel())
			.. ': "H" or "P" set id not found,' 
			.. ' please use |setid=... (H or P)'
	addPreviewMsg(sMsg)
	return
end

--------------------------------------------------------------------------------
-- formatPhraseAbbr
--
-- format phraseID and text, for abbr-form (infobox list form)
--------------------------------------------------------------------------------
local function formatPhraseAbbr(phraseID, sPhrase)
	return '<abbr class="abbr" title=" ' .. phraseID .. ': ' .. sPhrase .. '">'
				.. phraseID 
				.. '</abbr>'
end

--------------------------------------------------------------------------------
-- formatPhraseInline
--
-- format phraseID and text, for inline form (in sentence)
-- adds "quotes"
--------------------------------------------------------------------------------
local function formatPhraseInline(phraseID, sPhrase)
	return inMono(phraseID) .. ': \"' .. sPhrase .. '\"'
end

--------------------------------------------------------------------------------
-- formatPhraseList
--
-- as inline, but no "quotes" added.
--------------------------------------------------------------------------------
local function formatPhraseList(phraseID, sPhrase)
	return inMono(phraseID) .. ': ' .. sPhrase
end

--------------------------------------------------------------------------------
-- getSetID
--
-- Determines setID (expected either 'H' or 'P')
-- First route is: read |setid=
-- When |setid= is not set, 
--		it looks for a first parameter that has an H of P prefix (in |P201|P202|...)
--		when not found, 'GHS' is retured
-- In one call, P and H numbers can *not* be mixed
--		so "|H201|P202|" will cause error "P202 not found" (... in H-list)
--------------------------------------------------------------------------------
local function getSetID(tArgs)
	local setIDfound = 'GHS'
	local paramsetID = tArgs['setid'] or nil
	
	if (paramsetID ~= nil) and (paramsetID == 'P' or paramsetID == 'H') then
		setIDfound = paramsetID
	else
		local initial = nil
		for i, v in ipairs(tArgs) do
			initial = mw.ustring.match(v, '^[PH]')
			if initial ~=nil then
				setIDfound = initial
				break
			end
		end
	end
	return setIDfound
end

--------------------------------------------------------------------------------
-- getListType
--
-- Checks list format, including those from Module:List
--------------------------------------------------------------------------------
local function getListType(tArgs)
	local listTypes = {
	['abbr'] = true,
	['bulleted'] = true,
	['unbulleted'] = true,
	['horizontal'] = true,
	['ordered'] = true,
	['horizontal_ordered'] = true,
	['horizontal ordered'] = true,
	['inline'] = true
	}
	local sListType = tArgs['listtype'] or 'abbr'

	if sListType == '' or sListType == 'abbr' then
		return 'abbr'
	elseif listTypes[sListType] == true then
		if sListType == 'horizontal ordered' then
			sListType = 'horizontal_ordered'
		end
		return sListType
	else 
		sListType = 'abbr'
	end
	return sListType
end

--------------------------------------------------------------------------------
-- getDoOmitRules
--------------------------------------------------------------------------------
local function getDoOmitRules(tArgs)
	local b = yesno(tArgs['omit'], true)
	
	if b == nil then b = true end

	return yesno(b, true)
end

--------------------------------------------------------------------------------
-- prepareArgs
--
-- First: determine setID (from |setID= OR from prefixes in parameters)
-- Then: clean up & format phrase IDs (=unnamed parameters)
--		remove bad characters, create H/P pattern "H201", "P310+P302"
-- straight array, no nil's, sorted
--------------------------------------------------------------------------------
local function prepareArgs(tArgs)

	tArgName['setID'] = getSetID(tArgs)
	tArgName['listtype'] = getListType(tArgs)
	tArgName['omit'] = getDoOmitRules(tArgs)

	tArgs = tTools.compressSparseArray(tArgs) -- removes all named args
	if string.len(tArgName['setID']) == 1 and #tArgs > 0 then
		for i, v in ipairs(tArgs) do
			v = mw.text.decode(v)
			v = mw.ustring.gsub(v, '[^%d%+A-Za-z]', '')
			v = mw.ustring.gsub(v, '^(%d)', tArgName['setID'] .. '%1')
			v = mw.ustring.gsub(v, '%+(%d)', '+' .. tArgName['setID'] .. '%1')
			tArgs[i] = v
		end
		table.sort(tArgs)
	end
	return tArgs
end

--------------------------------------------------------------------------------
-- listAll
--
-- Returns wikitable rows for each phrase id.
-- requires |setID=P/H
-- returns full list, all phrases, for a setID
-- 2-columns wikitable, sorted, sortable, anchor like "H201" for each
--------------------------------------------------------------------------------
function r.listAll(frame)
local newArgs = getArgs(frame)
local tL = {}

	prepareArgs(newArgs)
	
	local tRead
	if tArgName['setID'] == 'H' then
		tRead = GHSdata['Hphrases']
	elseif tArgName['setID'] == 'P' then
		tRead = GHSdata['Pphrases']
	else 
		errorHPsetIDmissing()
		return  showPreviewMsg()
	end

	-- Intermediate table t2 to maintain order; read from original table (/data)
	local t2 = {}
	local iPh
	for s, v in pairs(tRead) do
		iPh = tonumber(mw.ustring.match(s, '[PH](%d%d%d)'))
		if string.len(s) > 4 then
			iPh = tTools.size(t2) + 1
		end
		table.insert(t2, iPh, s)
	end
	t2 = tTools.compressSparseArray(t2)
	table.sort(t2)

	local sTR, v, sAnchor
	-- i = array index, s = phraseID, v = phrase text
	for i, s in ipairs(t2) do
		v = tRead[s]
		sAnchor = '<span class="anchor" id="' .. s .. '"></span>'
		sTR = '|- ' .. sAnchor .. '\n| datasortvalue="' .. i .. '" | <span style="font-family: monospace;">' .. s .. '</span> || ' .. v
		table.insert(tL, sTR)
	end

	return table.concat(tL, '\n')
end

--------------------------------------------------------------------------------
-- numberOfPhrases
--
-- Documentation
-- requires |setID=H/P
-- Returns number of phrases, in format
--	"GHS H-phrases (123)"
--------------------------------------------------------------------------------
function r.numberOfPhrases(frame)
	local newArgs = getArgs(frame)

	prepareArgs(newArgs)

	local iT
	if tArgName['setID'] == 'H' then
		iT = tTools.size(GHSdata['Hphrases'])
	elseif tArgName['setID'] == 'P' then
		iT = tTools.size(GHSdata['Pphrases'])
	else
		errorHPsetIDmissing()
		return showPreviewMsg()
	end

	return 'GHS ' .. PHlabel() .. ' <span style="font-weight: normal;">(' .. tostring(iT) .. ')</span>'
end

--------------------------------------------------------------------------------
-- listOmitRules
--
-- self-documentation
--------------------------------------------------------------------------------
function r.listOmitRules()
local tRules = GHSdata['tOmitRules']
local tL = {}
local s

	s = wlHelpPage('Omit Rules')
		.. ': when the <i>keep</i> ID is present, do not show the <i>omit</i> ID phrase'
	table.insert(tL, s)
	for keep, omit in pairs (tRules) do
		s = '&bull; keep ' .. inMono(keep) .. ', omit ' .. inMono(omit)
		table.insert(tL, s)
	end
	return table.concat(tL, '<br/>')
end

--------------------------------------------------------------------------------
-- _main
--
-- processes setID (H, P) and phrase codes
--		error:	setID not P, H
--				code not found
-- cannot mix H and P phrases
-- reads phrases from /data H or P phrases tables
-- formats phrase (abbreviation, abbr-title, phraseID)
--------------------------------------------------------------------------------
function r._main(tArgs)

	tArgs = prepareArgs(tArgs)
	
	if #tArgs == 0 then
		return showPreviewMsg() -- no content
	elseif tArgName['setID'] == 'GHS' then
		return errorHPsetIDnotFound()
	end

	tArgs = applyRemoveDuplicates(tArgs)
	if tArgName['omit'] then
		tArgs = applyOmitRules(tArgs)
	end

	local formatterF
	if tArgName['listtype'] == 'abbr' then
		formatterF = formatPhraseAbbr
	elseif tArgName['listtype'] == 'inline' then
		formatterF = formatPhraseInline
	else --- Module:List options
		formatterF = formatPhraseList
	end
	
	local tReadD = {}
	if tArgName['setID'] == 'H' then
		tReadD = GHSdata['Hphrases']
	elseif tArgName['setID'] == 'P' then
		tReadD = GHSdata['Pphrases']
	else
		return showPreviewMsg()
	end

	local sPhrase
	local tR = {}
	for i, v in ipairs(tArgs) do
		sPhrase = tReadD[v]
		if sPhrase == nil then
			table.insert(tR, errorPhraseIDnotFound(tostring(v)))
		else
			table.insert(tR, formatterF(v, sPhrase))
		end
	end

	if tArgName['listtype'] == 'abbr' then
		return table.concat(tR, ', ') .. showPreviewMsg()
	elseif tArgName['listtype'] == 'inline' then
		return table.concat(tR, ', ') .. showPreviewMsg()
	else
		local mList = require('Module:List')
		return mList[tArgName['listtype']](tR) .. showPreviewMsg()
	end
end

--------------------------------------------------------------------------------
-- main
--
-- handles template input frame, then calls generic _main() function
-- To be invoked from {{template}}
--------------------------------------------------------------------------------
function r.main(frame)
local newArgs = getArgs(frame)
	return r._main(newArgs) 
end


return r