-- 구현을 위한 모듈입니다.
--

local p = {}

local navbar = require('모듈:Navbar')._navbar
local getArgs -- lazily initialized

local args
local tableRowAdded = false
local border
local listnums = {}

local function trim(s)
 return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end

local function addNewline(s)
 if s:match('^[*:;#]') or s:match('^{|') then
 return '\n' .. s ..'\n'
 else
 return s
 end
end

local function addTableRow(tbl)
 -- If any other rows have already been added, then we add a 2px gutter row.
 if tableRowAdded then
 tbl
 end

 tableRowAdded = true

 return tbl:tag('tr')
end

local function renderNavBar(titleCell)
 -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
 -- or right to keep the title centered.
 local spacerSide = nil

 if args['상태'] == 'off' then
 -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
 -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
 if args['상태'] == 'plain' then spacerSide = 'right' end
 elseif args.navbar == 'plain' or (not args['이름'] and mw.getCurrentFrame:getParent:getTitle:gsub == '틀:둘러보기 상자') then
 -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
 if args['상태'] ~= 'plain' then spacerSide = 'left' end
 else
 -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
 -- to balance out the width of the navbar.
 if args['상태'] == 'plain' then spacerSide = 'right' end

 titleCell:wikitext(navbar{
 args['이름'],
 mini = 1,
 fontstyle = (args['기반모양'] or '') .. ';' .. (args['제목모양'] or '') .. ';background:none transparent;border:none;'
 end

 -- Render the spacer div.
 if spacerSide then
 titleCell
 end
end

--
-- 제목 구문
--
local function renderTitleRow(tbl)
 if not args['제목'] then return end

 local titleRow = addTableRow(tbl)

 if args['제목묶음'] then
 titleRow
 end

 local titleCell = titleRow:tag('th'):attr

 if args['제목묶음'] then
 titleCell
 end

 local titleColspan = 2
 if args['왼쪽그림'] then titleColspan = titleColspan + 1 end
 if args['그림'] then titleColspan = titleColspan + 1 end
 if args['제목묶음'] then titleColspan = titleColspan - 1 end

 titleCell

 renderNavBar(titleCell)

 titleCell
end

--
-- 아랫글/윗글 구문
--

local function getAboveBelowColspan
 local ret = 2
 if args['왼쪽그림'] then ret = ret + 1 end
 if args['그림'] then ret = ret + 1 end
 return ret
end

local function renderAboveRow(tbl)
 if not args['윗글'] then return end

 addTableRow(tbl)
end

local function renderBelowRow(tbl)
 if not args['아랫글'] then return end

 addTableRow(tbl)
end

--
-- 내용 구문
--
local function renderListRow
 local row = addTableRow(tbl)

 if listnum == 1 and args['왼쪽그림'] then
 row
 end

 if args['묶음' .. listnum] then
 local groupCell = row:tag('th')

 groupCell

 if args['묶음너비'] then
 groupCell:css
 end

 groupCell
 end

 local listCell = row:tag('td')

 if args['묶음' .. listnum] then
 listCell
 else
 listCell:attr
 end

 if not args['묶음너비'] then
 listCell:css
 end

 local isOdd = (listnum % 2) == 1
 local rowstyle = args['짝수모양']
 if isOdd then rowstyle = args['홀수모양'] end

 local evenOdd
 if args.evenodd == 'swap' then
 if isOdd then evenOdd = 'even' else evenOdd = 'odd' end
 else
 if isOdd then evenOdd = args.evenodd or 'odd' else evenOdd = args.evenodd or 'even' end
 end

 listCell

 if listnum == 1 and args['그림'] then
 row
 end
end

--
-- 분류 추적
--

local function needsHorizontalLists
 if border == 'child' or border == 'subgorup' or args.tracking == 'no' then return false end

 local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
 for i, cls in ipairs(listClasses) do
 if args['내용속성'] == cls or args['내용속성'] == cls then
 return false
 end
 end

 return true
end

local function hasBackgroundColors
 return mw.ustring.match or mw.ustring.match or mw.ustring.match
end

local function isIllegible
 local styleratio = require('모듈:Color contrast')._styleratio

 for key, style in pairs(args) do
 if tostring(key):match("style$") then
 if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then
 return true 
 end
 end
 end
 return false
end

local function getTrackingCategories
 local cats = {}
 if needsHorizontalLists then table.insert end
 if hasBackgroundColors then table.insert end
 if isIllegible then table.insert end
 return cats
end

local function renderTrackingCategories(builder)
 local title = mw.title.getCurrentTitle
 if title.namespace ~= 10 then return end -- not in template space
 local subpage = title.subpageText
 if subpage == '설명문서' or subpage == '연습장' or subpage == '시험장' then return end

 for i, cat in ipairs(getTrackingCategories) do
 builder:wikitext('분류:' .. cat .. '')
 end
end

--
-- 둘러보기 상자 표 본문 구문
--
local function renderMainTable
 local tbl = mw.html.create('table')

 if args.title and (args['상태'] ~= 'plain' and args['상태'] ~= 'off') then
 tbl
 end

 tbl:css
 if border == 'subgroup' or border == 'child' or border == 'none' then
 tbl
 else -- regular navobx - bodystyle and style will be applied to the wrapper table
 tbl
 end
 tbl:cssText(args['내부모양'])

 renderTitleRow(tbl)
 renderAboveRow(tbl)
 for i, listnum in ipairs(listnums) do
 renderListRow
 end
 renderBelowRow(tbl)

 return tbl
end

function p._navbox(navboxArgs)
 args = navboxArgs

 for k, v in pairs(args) do
 local listnum = ('' .. k):match('^list(%d+)$')
 if listnum then table.insert(listnums, tonumber(listnum)) end
 end
 table.sort(listnums)

 border = trim(args['border'] or args[1] or '')

 -- render the main body of the navbox
 local tbl = renderMainTable

 -- render the appropriate wrapper around the navbox, depending on the border param
 local res = mw.html.create
 if border == 'none' then
 res:node(tbl)
 elseif border == 'subgroup' or border == 'child' then
 -- We assume that this navbox is being rendered in a list cell of a parent navbox, and is
 -- therefore inside a div with padding:0em 0.25em. We start with a  to avoid the
 -- padding being applied, and at the end add a 
 res
 else
 res
 end

 renderTrackingCategories(res)

 return tostring(res)
end

function p.navbox(frame)
 if not getArgs then
 getArgs = require('모듈:Arguments').getArgs
 end
 args = getArgs

 -- Read the arguments in the order they'll be output in, to make references number in the right order.
 local _
 _ = args['제목']
 _ = args['윗글']
 for i = 1, 20 do
 _ = args["묶음" .. tostring(i)]
 _ = args["내용" .. tostring(i)]
 end
 _ = args['아랫글']

 return p._navbox(args)
end