• Welcome to the Kancolle Wiki!
  • If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord

Difference between revisions of "Module:ShipPage"

From Kancolle Wiki
Jump to navigation Jump to search
m
m (166 revisions imported)
 
(158 intermediate revisions by 4 users not shown)
Line 1: Line 1:
local Utils = require("Module:Utils")
+
local U = require("Module:Core")
local format = require("Module:StringOperations").format
+
local format = require("Module:Core").format
 
local Formatting = require("Module:Formatting")
 
local Formatting = require("Module:Formatting")
 
local BaseData = require("Module:BaseData")
 
local BaseData = require("Module:BaseData")
 
local Ship = require("Module:Ship")
 
local Ship = require("Module:Ship")
 
+
local ShipGraphicKai = require('Module:ShipGraphicKai')
-- [[Category:Todo]]: support passing Ship object in those modules, use Ship object, redo and move ship_remodel_forms function
+
local ShipCardKai = require('Module:ShipCardKai')
 +
local ShipBattleCardKai = require('Module:ShipBattleCardKai')
 
local ShipMetaKai = require("Module:ShipMetaKai")
 
local ShipMetaKai = require("Module:ShipMetaKai")
 
local ShipInfoKai = require("Module:ShipInfoKai")
 
local ShipInfoKai = require("Module:ShipInfoKai")
 
local ShipCategoriesKai = require("Module:ShipCategoriesKai")
 
local ShipCategoriesKai = require("Module:ShipCategoriesKai")
  
function ship_remodel_forms(ship_name)
+
-- can't use Ship:remodel_to_level() normally for some reason
     local success, ship_data = Utils.requireModule(ship_name)
+
local reversible_forms = {}
    local forms = { ship_name }
+
 
 +
function ship_remodel_forms(ship_name, seasonal_forms, ship_suffix, j)
 +
    j = j or 1
 +
    ship_suffix = ship_suffix or ""
 +
    local forms = { ship_name .. "/" .. ship_suffix }
 +
     local success, ship_data = Ship.requireModule(ship_name)
 
     if not success then
 
     if not success then
        table.insert(forms, string.format("%s/Kai", ship_name))
 
 
         return forms
 
         return forms
 
     end
 
     end
     local form_data = ship_data[""]
+
     local form_data = ship_data[ship_suffix]
 +
    if seasonal_forms then
 +
        for suffix, data in pairs(ship_data) do
 +
            if (data._seasonal == true or data._season) and data._name and data._suffix then
 +
                table.insert(seasonal_forms, data._name .. "/" .. data._suffix)
 +
            end
 +
        end
 +
    end
 
     local i = 0
 
     local i = 0
     while form_data and form_data._remodel_to and not Utils.find(forms, form_data._remodel_to) and i < 10 do
+
     while form_data and form_data._remodel_to and not U.find(forms, form_data._remodel_to) and i < 10 and j <= 3 do
         table.insert(forms, form_data._remodel_to)
+
         local ship_name_next, ship_suffix_next = Ship:process_ship_key(form_data._remodel_to)
         local ship_base_name, ship_suffix = Ship:process_ship_key(form_data._remodel_to)
+
         if ship_name_next ~= ship_name then
        form_data = ship_data[ship_suffix]
+
            return U.concat(forms, ship_remodel_forms(ship_name_next, seasonal_forms, ship_suffix_next, j + 1))
 +
        else
 +
            table.insert(forms, form_data._remodel_to)
 +
            form_data = ship_data[ship_suffix_next]
 +
            if form_data._remodel_to_level then
 +
                reversible_forms[form_data._name .. "/" .. (form_data._suffix or "")] = form_data._remodel_to
 +
            end
 +
        end
 
         i = i + 1
 
         i = i + 1
 
     end
 
     end
Line 30: Line 49:
 
local ShipPage = {
 
local ShipPage = {
  
     _header = "${ship_meta}__TOC__${clear}${ship_infoboxes}${ship_categories}",
+
     _header = "${notice}${ship_meta}__TOC__${clear}${ship_infoboxes}${ship_categories}",
  
 
     _ship_infobox = [[<div style="display:inline-block;">
 
     _ship_infobox = [[<div style="display:inline-block;">
Line 41: Line 60:
 
         "Upgrade",
 
         "Upgrade",
 
         "Second Upgrade",
 
         "Second Upgrade",
         "Third Upgrade (Reversible)"
+
         "Third Upgrade",
 +
        "Fourth Upgrade",
 +
        "Fifth Upgrade"
 
     },
 
     },
  
     _footer_links = [=[*[[${ship_name}/Gallery|View ${ship_name} CG]]
+
     _gallery_link = [=[*[[${fullpagename}/Gallery|View ${ship_name} CG]]]=],
*[[${ship_code}|List of ${ship_type}s]]
+
    _ship_type_link = [=[*[[${ship_code}|List of ${ship_type}s]]]=],
*[[wikipedia:${wikipedia}|Wikipedia entry on ${ship_type} ${ship_name}]]]=],
+
    _wikipedia_link = [=[*[[wikipedia:${wikipedia}|Wikipedia entry on ${ship_type} ${ship_name}]]]=],
 +
 
 +
    _sandbox_notice = [=[<div style="width:90%; border:2px solid #aa5; background:#ffc; text-align:center; margin:15px auto 20px; padding:5px;">This is a testing ship page, it does not correspond to an actual ship.</div>
 +
]=],
 +
 
 +
    _dd_notice = [=[<div style="width:90%; border:2px solid #aa5; background:#ffc; text-align:center; margin:15px auto 20px; padding:5px;">As part of the [[Thread:670693|Phase 2]] update, some remodels have had stock equipments changed, which may not yet be reflected on these pages. Please be patient while they are brought up to date.</div>
 +
]=],
 +
 
 +
    _gallery_tabber = [[<div class="ship-page-gallery-tab">
 +
{{#tag:tabber|
 +
{{!}}-{{!}}Normal=${image}
 +
{{!}}-{{!}}Damaged=${image_damaged}
 +
}}
 +
</div>]],
 +
 
 +
    _gallery_normal = [[<div class="ship-page-gallery-tab">
 +
{{#tag:tabber|
 +
{{!}}-{{!}}Normal=${image}
 +
}}
 +
</div>]],
 +
 
 +
    _gallery_damaged = [[<div class="ship-page-gallery-tab">
 +
{{#tag:tabber|
 +
{{!}}-{{!}}Damaged=${image}
 +
}}
 +
</div>]],
 +
 
 +
    _footer_sections = [=[<div class="ship-page-gallery">
 +
==[[${name}/Gallery|CG]]==
 +
${gallery}
 +
</div>
 +
==See Also==
 +
${links}]=],
  
 
}
 
}
Line 54: Line 107:
 
end
 
end
  
function ShipPage:format_ship_infoboxes()
+
function ShipPage:format_ship_infoboxes(basepagename)
 
     local forms = ship_remodel_forms(self._vars.ship_name)
 
     local forms = ship_remodel_forms(self._vars.ship_name)
 
     local infoboxes = {}
 
     local infoboxes = {}
 
     for i, form in ipairs(forms) do
 
     for i, form in ipairs(forms) do
 +
        local override
 +
        if basepagename == "Sandbox" then
 +
            override = { _page = "Sandbox/" .. self._vars.ship_name }
 +
        end
 +
        local reverse_form_suffix
 +
        if reversible_forms[form] then
 +
            local lua_huh, reverse_form_suffix_ = Ship:process_ship_key(reversible_forms[form])
 +
            reverse_form_suffix = reverse_form_suffix_
 +
        end
 
         table.insert(infoboxes, format{
 
         table.insert(infoboxes, format{
 
             self._ship_infobox,
 
             self._ship_infobox,
             title = self._ship_infobox_titles[i],
+
             title = (self._ship_infobox_titles[i] or "?") ..
             infobox = ShipInfoKai:Infobox({ form })
+
              (reverse_form_suffix and string.format(" (Reversible to %s)", reverse_form_suffix) or ""),
 +
             infobox = ShipInfoKai:Infobox({ form, override = override })
 
         })
 
         })
 
     end
 
     end
Line 67: Line 130:
 
end
 
end
  
function ShipPage:format_ship_categories()
+
function ShipPage:format_ship_categories(basepagename, args)
     self._vars.ship_categories = ShipCategoriesKai:Categories({ self._vars.ship_name })
+
     self._vars.ship_categories = (basepagename == "Sandbox" or args.no_categories) and "" or ShipCategoriesKai:Categories({ self._vars.ship_name })
 
end
 
end
  
function ShipPage:format_header(ship_name)
+
function ShipPage:format_notice(basepagename)
 +
    self._vars.notice = basepagename == "Sandbox" and self._sandbox_notice or "" -- Ship(basepagename):type() == 2 and self._dd_notice or ""
 +
end
 +
 
 +
function ShipPage:format_header(ship_name, basepagename, args)
 
     self._vars = {
 
     self._vars = {
 
         ship_name = ship_name,
 
         ship_name = ship_name,
Line 77: Line 144:
 
     }
 
     }
 
     self:format_ship_meta()
 
     self:format_ship_meta()
     self:format_ship_infoboxes()
+
     self:format_ship_infoboxes(basepagename)
     self:format_ship_categories()
+
     self:format_ship_categories(basepagename, args)
 +
    self:format_notice(basepagename)
 
     return format(self._header, self._vars)
 
     return format(self._header, self._vars)
 
end
 
end
  
function ShipPage.Header(frame, args)
+
function ShipPage.Header(frame)
     args = args or Utils.getTemplateArgs(frame)
+
     local args = U.getTemplateArgs(frame)
 +
    local basepagename = args.implicit.basepagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
     return ShipPage:format_header(ship_name)
+
     return ShipPage:format_header(ship_name, basepagename, args.explicit)
 
end
 
end
  
function ShipPage.FooterLinks(frame, args)
+
function ShipPage.FooterLinks(args)
     args = args or Utils.getTemplateArgs(frame)
+
     local basepagename = args.implicit.basepagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
 
     local ship = Ship(ship_name)
 
     local ship = Ship(ship_name)
 
     local ship_type = ship:type()
 
     local ship_type = ship:type()
     return format{
+
     local ship_name_ = ship:name()
        ShipPage._footer_links,
+
    local ship_type_ = Formatting:format_ship_type(ship_type)
        ship_name = ship_name,
+
    local ship_code = Formatting:format_ship_code(ship_type)
        ship_code = Formatting:format_ship_code(ship_type),
+
    local wikipedia = ship:wikipedia()
        ship_type = Formatting:format_ship_type(ship_type),
+
    local fullpagename = basepagename == "Sandbox" and ("Sandbox/" .. ship_name) or ship_name
        wikipedia = ship:wikipedia(),
+
    local links = {
 +
        format{
 +
            ShipPage._gallery_link,
 +
            fullpagename = fullpagename,
 +
            ship_name = ship_name_,
 +
        }
 
     }
 
     }
 +
    if ship_type then
 +
        table.insert(links, format{
 +
            ShipPage._ship_type_link,
 +
            ship_code = ship_code,
 +
            ship_type = ship_type_,
 +
        })
 +
    end
 +
    if wikipedia then
 +
        table.insert(links, format{
 +
            ShipPage._wikipedia_link,
 +
            ship_name = ship_name_,
 +
            ship_type = ship_type_,
 +
            wikipedia = wikipedia,
 +
        })
 +
    end
 +
    if args.explicit.links then
 +
        links = U.concat(links, args.explicit.links)
 +
    end
 +
    return table.concat(links, "\n")
 
end
 
end
  
 
function ShipPage.ClassTemplate(frame, args)
 
function ShipPage.ClassTemplate(frame, args)
     args = args or Utils.getTemplateArgs(frame)
+
     args = args or U.getTemplateArgs(frame)
 +
    local basepagename = args.implicit.basepagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
 
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
 
     local ship = Ship(ship_name)
 
     local ship = Ship(ship_name)
     return ship:class() and ship:class():name() or "Unknown Class"
+
     local classI = ship:class()
 +
    local class = classI and classI:name_override() or "Unknown Class"
 +
    if basepagename == "Sandbox" then
 +
        return "Sandbox/" .. class
 +
    else
 +
        return class
 +
    end
 
end
 
end
  
--[[
+
function ShipPage.ClassTemplateTest(frame)
ShipPage.t1 = ShipPage.Header(nil, {
+
    local args = U.getTemplateArgs(frame)
     explicit = { ship = "Ayanami" },
+
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
     implicit = {},
+
     local ship = Ship(ship_name)
})
+
    local classI = ship:class()
-- print(p.t1)
+
    local class = classI and classI:base_name_test() or "?"
 +
    return string.format("|%s|%s|%s|", ship_name, ship:name(), tostring(class))
 +
end
  
ShipPage.t2 = ShipPage.Header(nil, {
+
function ship_cgs(ship_name, ship_suffix, j, seasonal_forms, visited_modules)
    explicit = { ship = "Hibiki" },
+
ship_suffix = ship_suffix or ""
     implicit = {},
+
    j = j or 1
})
+
    seasonal_forms = seasonal_forms or {}
-- print(p.t2)
+
    visited_modules = visited_modules or {}
 +
    local forms = { { name = ship_name .. '/' .. ship_suffix, normal = true, damaged = true } }
 +
    local success, ship_data = Ship.requireModule(ship_name)
 +
    if not success then
 +
        return forms
 +
    end
 +
    if not U.ifind(visited_modules, ship_name) then
 +
    table.insert(visited_modules, ship_name)
 +
    -- TODO: legacy seasonals, check if it is ok to delete
 +
    for suffix, data in pairs(ship_data) do
 +
        if data._seasonal or data._season then
 +
            local normal = data._cg ~= false
 +
            local damaged = data._cg_damaged ~= false
 +
            table.insert(seasonal_forms, {
 +
                suffux = data._suffix or suffix,
 +
                name = (data._name or ship_name) .. "/" .. (data._suffix or suffix),
 +
                seasonal = true,
 +
                normal = normal,
 +
                damaged = damaged,
 +
                season = data._season,
 +
                season_suffix = data._season_suffix,
 +
                battle_card = data._show_battle_card,
 +
            })
 +
        end
 +
    end
 +
    for _, data in ipairs(ship_data.seasonals or {}) do
 +
        local normal = data._cg ~= false
 +
        local damaged = data._cg_damaged ~= false
 +
        table.insert(seasonal_forms, {
 +
            suffux = data._suffix,
 +
            name = (data._name or ship_name) .. "/" .. data._suffix,
 +
            seasonal = true,
 +
            normal = normal,
 +
            damaged = damaged,
 +
            season = data._season,
 +
            season_suffix = data._season_suffix,
 +
            battle_card = data._show_battle_card,
 +
        })
 +
    end
 +
    end
 +
    local i = 1
 +
    local form_data = ship_data[ship_suffix]
 +
    while form_data and form_data._remodel_to and not U.find(forms, form_data._remodel_to, 'name') and i <= 15 and j <= 3 do
 +
        local ship_name_next, ship_suffix_next = Ship:process_ship_key(form_data._remodel_to)
 +
        if ship_name_next ~= ship_name then
 +
            return U.concat(forms, ship_cgs(ship_name_next, ship_suffix_next, j + 1, seasonal_forms, visited_modules))
 +
        else
 +
            local name = form_data._remodel_to
 +
            form_data = ship_data[ship_suffix_next]
 +
            local normal = not (form_data._cg_reference and true or false)
 +
            local damaged = not (form_data._cg_damaged_reference and true or false)
 +
            table.insert(forms, { name = name, normal = normal, damaged = damaged })
 +
        end
 +
        i = i + 1
 +
    end
 +
    return U.concat(forms, seasonal_forms)
 +
end
 +
 
 +
function cg(seasonal, name, damaged, size, battle_card)
 +
    return format{
 +
        [[<span class="advanced-tooltip">${cg}<div class="tooltip-contents">${card}${battle_card}</div></span>]],
 +
        cg = ShipGraphicKai:Asset({ name, link = "nil", damaged = damaged, size = size, hd = true }),
 +
        card = ShipCardKai:Asset({ name, link = "nil", damaged = damaged, hd = true }),
 +
        battle_card = battle_card and ("<br>" .. ShipBattleCardKai:Asset({ name, link = "nil", damaged = damaged, hd = true })) or "",
 +
     }
 +
end
 +
 
 +
function getFirstSeason(season)
 +
    if type(season) == "table" then
 +
        if type(season[1]) == "table" then
 +
            return season[1][1]
 +
        else
 +
            return season[1]
 +
        end
 +
    else
 +
        return season
 +
    end
 +
end
 +
 
 +
function formatSeason(season)
 +
    local seasons = type(season) == "table" and season or { season }
 +
    local strings = U.imap(seasons, function(season)
 +
        if type(season) == "table" then
 +
            return format{"[[Seasonal/${season_link}|${season_name}]]", season_link = season[1], season_name = season[2]}
 +
        else
 +
            return format{"[[Seasonal/${season}|${season}]]", season = season}
 +
        end
 +
    end)
 +
    return table.concat(strings, ", ")
 +
end
 +
 
 +
function getTitle(form, base_name, name, suffix, short)
 +
    if form.seasonal then
 +
        if short then
 +
            if form.season_suffix == false then
 +
                return nil
 +
            end
 +
            if form.season_suffix then
 +
                return form.season_suffix
 +
            end
 +
            local season = getFirstSeason(form.season) or "" -- string.match(form.season, "(.*) 20%d%d") or form.season
 +
            local suffixInSeason = string.find(season, suffix)
 +
            local seasonInSuffix = string.find(suffix, season)
 +
            if suffixInSeason then
 +
                return name ~= base_name and name
 +
            elseif seasonInSuffix then
 +
                return string.sub(suffix, 1, seasonInSuffix - 2)
 +
            else
 +
                return name == base_name and suffix or name .. " " .. suffix
 +
            end
 +
        else
 +
            return name == base_name and suffix or name .. " " .. suffix
 +
        end
 +
    else
 +
        return suffix ~= "" and suffix or name == base_name and "Base" or name
 +
    end
 +
end
  
ShipPage.t3 = ShipPage.Header(nil, {
+
local blur_options = [=[<div style="margin-top:5px;text-align:right">
    explicit = { ship = "Zuikaku" },
+
<div class="toggle" data-target="nsfw" data-default="hide" data-classes="blur">
    implicit = {},
+
<span class="toggle-show" style="cursor:pointer;color:#006cb0;">☑ Blur NSFW CG</span>
})
+
<span class="toggle-hide" style="cursor:pointer;color:#006cb0;">☒ Blur NSFW CG</span>
-- print(p.t3)
+
</div>
 +
<div class="toggle" data-target="nsfw-damaged" data-default="hide" data-classes="blur">
 +
<span class="toggle-show" style="cursor:pointer;color:#006cb0;">☑ Blur other damaged CG</span>
 +
<span class="toggle-hide" style="cursor:pointer;color:#006cb0;">☒ Blur other damaged CG</span>
 +
</div>
 +
</div>]=]
  
ShipPage.t4 = ShipPage.Header(nil, {
+
function ShipPage.Gallery(frame, args)
     explicit = {},
+
    args = args or U.getTemplateArgs(frame)
    implicit = {},
+
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
})
+
    local forms = ship_cgs(ship_name)
-- print(p.t4)
+
    local result = { '<div class="ship-gallery-page">' }
 +
    local first_seasonal
 +
    for _, form in ipairs(forms) do
 +
        local name, suffix = Ship:process_ship_key(form.name)
 +
        suffix = suffix or ""
 +
        local title = getTitle(form, ship_name, name, suffix, true)
 +
        if not first_seasonal and form.seasonal then
 +
            first_seasonal = true
 +
            table.insert(result, "<h2>[[Seasonal]]s</h2>")
 +
        end
 +
        if form.seasonal and (form.normal or form.damaged) then
 +
            if form.season and not title then
 +
                table.insert(result, format{
 +
                    "<h3>${seasons}</h3>",
 +
                    seasons = formatSeason(form.season)
 +
                })
 +
            elseif form.season then
 +
                table.insert(result, format{
 +
                    "<h3>${seasons} (${title})</h3>",
 +
                    title = title,
 +
                    seasons = formatSeason(form.season)
 +
                })
 +
            else
 +
                table.insert(result, "<h3>" .. title .. "</h3>")
 +
            end
 +
        elseif form.normal or form.damaged then
 +
            table.insert(result, "<h2>" .. title .. "</h2>")
 +
        end
 +
        table.insert(result, '<div class="ship-gallery-page-section">')
 +
        if form.normal then
 +
            table.insert(result, '<div class="ship-gallery-page-section-image">')
 +
            table.insert(result, cg(form.seasonal, form.name))
 +
            table.insert(result, "</div>")
 +
        end
 +
        if form.damaged then
 +
            table.insert(result, '<div class="ship-gallery-page-section-image">')
 +
            table.insert(result, cg(form.seasonal, form.name, true))
 +
            table.insert(result, "</div>")
 +
        end
 +
        table.insert(result, "</div>")
 +
    end
 +
    table.insert(result, "</div>")
 +
    table.insert(result, blur_options)
 +
     return table.concat(result, "\n")
 +
end
 +
 
 +
function ShipPage.GalleryTabber(args)
 +
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
 +
    local forms = ship_cgs(ship_name)
 +
    local result = { "{{#tag:tabber|" }
 +
    for _, form in ipairs(forms) do
 +
        if form.normal or form.damaged then
 +
            local name, suffix = Ship:process_ship_key(form.name)
 +
            suffix = suffix or ""
 +
            local title = getTitle(form, ship_name, name, suffix)
 +
            table.insert(result, "{{!}}-{{!}}" .. title .. "=")
 +
            if form.normal and form.damaged then
 +
                local image = cg(form.seasonal, form.name, false, "300px", form.battle_card or not form.seasonal)
 +
                local image_damaged = cg(form.seasonal, form.name, true, "300px", form.battle_card or not form.seasonal)
 +
                table.insert(result, format{
 +
                    ShipPage._gallery_tabber,
 +
                    image = image,
 +
                    image_damaged = image_damaged
 +
                })
 +
            elseif form.normal then
 +
                local image = cg(form.seasonal, form.name, false, "300px", form.battle_card or not form.seasonal)
 +
                table.insert(result, format{
 +
                    ShipPage._gallery_normal,
 +
                    image = image,
 +
                })
 +
            elseif form.damaged then
 +
                local image_damaged = cg(form.seasonal, form.name, true, "300px", form.battle_card or not form.seasonal)
 +
                table.insert(result, format{
 +
                    ShipPage._gallery_damaged,
 +
                    image = image_damaged,
 +
                })
 +
            end
 +
        end
 +
    end
 +
    table.insert(result, "}}")
 +
    table.insert(result, blur_options)
 +
    return table.concat(result, "\n")
 +
end
  
ShipPage.t5 = ShipPage.FooterLinks(nil, {
+
function ShipPage.BreakInstance(frame)
     explicit = { ship = "Ayanami" },
+
    local args = U.getTemplateArgs(frame)
     implicit = {},
+
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
})
+
     local forms = ship_cgs(ship_name)
-- print(p.t5)
+
    return "<pre>\n" .. U.js(Ship(ship_name)) .. "\n</pre>"
 +
end
  
ShipPage.t6 = ShipPage.ClassTemplate(nil, {
+
function ShipPage.FooterSections(frame)
     explicit = { ship = "Matsukaze" },
+
    local args = U.getTemplateArgs(frame)
    implicit = {},
+
     local ship_name = args.explicit.ship or args.implicit.pagename or ""
})
+
    return format{
-- print(p.t6)
+
        ShipPage._footer_sections,
]]--
+
        name = ship_name,
 +
        gallery = frame:preprocess(ShipPage.GalleryTabber(args)),
 +
        links = ShipPage.FooterLinks(args)
 +
    }
 +
end
  
 
return ShipPage
 
return ShipPage

Latest revision as of 12:45, 12 May 2021

Documentation for this module may be created at Module:ShipPage/doc

local U = require("Module:Core")
local format = require("Module:Core").format
local Formatting = require("Module:Formatting")
local BaseData = require("Module:BaseData")
local Ship = require("Module:Ship")
local ShipGraphicKai = require('Module:ShipGraphicKai')
local ShipCardKai = require('Module:ShipCardKai')
local ShipBattleCardKai = require('Module:ShipBattleCardKai')
local ShipMetaKai = require("Module:ShipMetaKai")
local ShipInfoKai = require("Module:ShipInfoKai")
local ShipCategoriesKai = require("Module:ShipCategoriesKai")

-- can't use Ship:remodel_to_level() normally for some reason
local reversible_forms = {}

function ship_remodel_forms(ship_name, seasonal_forms, ship_suffix, j)
    j = j or 1
    ship_suffix = ship_suffix or ""
    local forms = { ship_name .. "/" .. ship_suffix }
    local success, ship_data = Ship.requireModule(ship_name)
    if not success then
        return forms
    end
    local form_data = ship_data[ship_suffix]
    if seasonal_forms then
        for suffix, data in pairs(ship_data) do
            if (data._seasonal == true or data._season) and data._name and data._suffix then
                table.insert(seasonal_forms, data._name .. "/" .. data._suffix)
            end
        end
    end
    local i = 0
    while form_data and form_data._remodel_to and not U.find(forms, form_data._remodel_to) and i < 10 and j <= 3 do
        local ship_name_next, ship_suffix_next = Ship:process_ship_key(form_data._remodel_to)
        if ship_name_next ~= ship_name then
            return U.concat(forms, ship_remodel_forms(ship_name_next, seasonal_forms, ship_suffix_next, j + 1))
        else
            table.insert(forms, form_data._remodel_to)
            form_data = ship_data[ship_suffix_next]
            if form_data._remodel_to_level then
                 reversible_forms[form_data._name .. "/" .. (form_data._suffix or "")] = form_data._remodel_to
            end
        end
        i = i + 1
    end
    return forms
end

local ShipPage = {

    _header = "${notice}${ship_meta}__TOC__${clear}${ship_infoboxes}${ship_categories}",

    _ship_infobox = [[<div style="display:inline-block;">
===${title}===
${infobox}
</div>]],

    _ship_infobox_titles = {
        "Basic",
        "Upgrade",
        "Second Upgrade",
        "Third Upgrade",
        "Fourth Upgrade",
        "Fifth Upgrade"
    },

    _gallery_link = [=[*[[${fullpagename}/Gallery|View ${ship_name} CG]]]=],
    _ship_type_link = [=[*[[${ship_code}|List of ${ship_type}s]]]=],
    _wikipedia_link = [=[*[[wikipedia:${wikipedia}|Wikipedia entry on ${ship_type} ${ship_name}]]]=],

    _sandbox_notice = [=[<div style="width:90%; border:2px solid #aa5; background:#ffc; text-align:center; margin:15px auto 20px; padding:5px;">This is a testing ship page, it does not correspond to an actual ship.</div>
]=],

    _dd_notice = [=[<div style="width:90%; border:2px solid #aa5; background:#ffc; text-align:center; margin:15px auto 20px; padding:5px;">As part of the [[Thread:670693|Phase 2]] update, some remodels have had stock equipments changed, which may not yet be reflected on these pages. Please be patient while they are brought up to date.</div>
]=],

    _gallery_tabber = [[<div class="ship-page-gallery-tab">
{{#tag:tabber|
{{!}}-{{!}}Normal=${image}
{{!}}-{{!}}Damaged=${image_damaged}
}}
</div>]],

    _gallery_normal = [[<div class="ship-page-gallery-tab">
{{#tag:tabber|
{{!}}-{{!}}Normal=${image}
}}
</div>]],

    _gallery_damaged = [[<div class="ship-page-gallery-tab">
{{#tag:tabber|
{{!}}-{{!}}Damaged=${image}
}}
</div>]],

    _footer_sections = [=[<div class="ship-page-gallery">
==[[${name}/Gallery|CG]]==
${gallery}
</div>
==See Also==
${links}]=],

}

function ShipPage:format_ship_meta()
    self._vars.ship_meta = ShipMetaKai:Infobox({ self._vars.ship_name })
end

function ShipPage:format_ship_infoboxes(basepagename)
    local forms = ship_remodel_forms(self._vars.ship_name)
    local infoboxes = {}
    for i, form in ipairs(forms) do
        local override
        if basepagename == "Sandbox" then
            override = { _page = "Sandbox/" .. self._vars.ship_name }
        end
        local reverse_form_suffix
        if reversible_forms[form] then
            local lua_huh, reverse_form_suffix_ = Ship:process_ship_key(reversible_forms[form])
            reverse_form_suffix = reverse_form_suffix_
        end
        table.insert(infoboxes, format{
            self._ship_infobox,
            title = (self._ship_infobox_titles[i] or "?") ..
              (reverse_form_suffix and string.format(" (Reversible to %s)", reverse_form_suffix) or ""),
            infobox = ShipInfoKai:Infobox({ form, override = override })
        })
    end
    self._vars.ship_infoboxes = table.concat(infoboxes, "\n")
end

function ShipPage:format_ship_categories(basepagename, args)
    self._vars.ship_categories = (basepagename == "Sandbox" or args.no_categories) and "" or ShipCategoriesKai:Categories({ self._vars.ship_name })
end

function ShipPage:format_notice(basepagename)
    self._vars.notice = basepagename == "Sandbox" and self._sandbox_notice or "" -- Ship(basepagename):type() == 2 and self._dd_notice or ""
end

function ShipPage:format_header(ship_name, basepagename, args)
    self._vars = {
        ship_name = ship_name,
        clear = Formatting:clear(),
    }
    self:format_ship_meta()
    self:format_ship_infoboxes(basepagename)
    self:format_ship_categories(basepagename, args)
    self:format_notice(basepagename)
    return format(self._header, self._vars)
end

function ShipPage.Header(frame)
    local args = U.getTemplateArgs(frame)
    local basepagename = args.implicit.basepagename or ""
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    return ShipPage:format_header(ship_name, basepagename, args.explicit)
end

function ShipPage.FooterLinks(args)
    local basepagename = args.implicit.basepagename or ""
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local ship = Ship(ship_name)
    local ship_type = ship:type()
    local ship_name_ = ship:name()
    local ship_type_ = Formatting:format_ship_type(ship_type)
    local ship_code = Formatting:format_ship_code(ship_type)
    local wikipedia = ship:wikipedia()
    local fullpagename = basepagename == "Sandbox" and ("Sandbox/" .. ship_name) or ship_name
    local links = {
        format{
            ShipPage._gallery_link,
            fullpagename = fullpagename,
            ship_name = ship_name_,
        }
    }
    if ship_type then
        table.insert(links, format{
            ShipPage._ship_type_link,
            ship_code = ship_code,
            ship_type = ship_type_,
        })
    end
    if wikipedia then
        table.insert(links, format{
            ShipPage._wikipedia_link,
            ship_name = ship_name_,
            ship_type = ship_type_,
            wikipedia = wikipedia,
        })
    end
    if args.explicit.links then
        links = U.concat(links, args.explicit.links)
    end
    return table.concat(links, "\n")
end

function ShipPage.ClassTemplate(frame, args)
    args = args or U.getTemplateArgs(frame)
    local basepagename = args.implicit.basepagename or ""
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local ship = Ship(ship_name)
    local classI = ship:class()
    local class = classI and classI:name_override() or "Unknown Class"
    if basepagename == "Sandbox" then
        return "Sandbox/" .. class
    else
        return class
    end
end

function ShipPage.ClassTemplateTest(frame)
    local args = U.getTemplateArgs(frame)
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local ship = Ship(ship_name)
    local classI = ship:class()
    local class = classI and classI:base_name_test() or "?"
    return string.format("|%s|%s|%s|", ship_name, ship:name(), tostring(class))
end

function ship_cgs(ship_name, ship_suffix, j, seasonal_forms, visited_modules)
	ship_suffix = ship_suffix or ""
    j = j or 1
    seasonal_forms = seasonal_forms or {}
    visited_modules = visited_modules or {}
    local forms = { { name = ship_name .. '/' .. ship_suffix, normal = true, damaged = true } }
    local success, ship_data = Ship.requireModule(ship_name)
    if not success then
        return forms
    end
    if not U.ifind(visited_modules, ship_name) then
    	table.insert(visited_modules, ship_name)
    	-- TODO: legacy seasonals, check if it is ok to delete
	    for suffix, data in pairs(ship_data) do
	        if data._seasonal or data._season then
	            local normal = data._cg ~= false
	            local damaged = data._cg_damaged ~= false
	            table.insert(seasonal_forms, {
	                suffux = data._suffix or suffix,
	                name = (data._name or ship_name) .. "/" .. (data._suffix or suffix),
	                seasonal = true,
	                normal = normal,
	                damaged = damaged,
	                season = data._season,
	                season_suffix = data._season_suffix,
	                battle_card = data._show_battle_card,
	            })
	        end
	    end
	    for _, data in ipairs(ship_data.seasonals or {}) do
	        local normal = data._cg ~= false
	        local damaged = data._cg_damaged ~= false
	        table.insert(seasonal_forms, {
	            suffux = data._suffix,
	            name = (data._name or ship_name) .. "/" .. data._suffix,
	            seasonal = true,
	            normal = normal,
	            damaged = damaged,
	            season = data._season,
	            season_suffix = data._season_suffix,
	            battle_card = data._show_battle_card,
	        })
	    end
    end
    local i = 1
    local form_data = ship_data[ship_suffix]
    while form_data and form_data._remodel_to and not U.find(forms, form_data._remodel_to, 'name') and i <= 15 and j <= 3 do
        local ship_name_next, ship_suffix_next = Ship:process_ship_key(form_data._remodel_to)
        if ship_name_next ~= ship_name then
            return U.concat(forms, ship_cgs(ship_name_next, ship_suffix_next, j + 1, seasonal_forms, visited_modules))
        else
            local name = form_data._remodel_to
            form_data = ship_data[ship_suffix_next]
            local normal = not (form_data._cg_reference and true or false)
            local damaged = not (form_data._cg_damaged_reference and true or false)
            table.insert(forms, { name = name, normal = normal, damaged = damaged })
        end
        i = i + 1
    end
    return U.concat(forms, seasonal_forms)
end

function cg(seasonal, name, damaged, size, battle_card)
    return format{
        [[<span class="advanced-tooltip">${cg}<div class="tooltip-contents">${card}${battle_card}</div></span>]],
        cg = ShipGraphicKai:Asset({ name, link = "nil", damaged = damaged, size = size, hd = true }),
        card = ShipCardKai:Asset({ name, link = "nil", damaged = damaged, hd = true }),
        battle_card = battle_card and ("<br>" .. ShipBattleCardKai:Asset({ name, link = "nil", damaged = damaged, hd = true })) or "",
    }
end

function getFirstSeason(season)
    if type(season) == "table" then
        if type(season[1]) == "table" then
            return season[1][1]
        else
            return season[1]
        end
    else
        return season
    end
end

function formatSeason(season)
    local seasons = type(season) == "table" and season or { season }
    local strings = U.imap(seasons, function(season)
        if type(season) == "table" then
            return format{"[[Seasonal/${season_link}|${season_name}]]", season_link = season[1], season_name = season[2]}
        else
            return format{"[[Seasonal/${season}|${season}]]", season = season}
        end
    end)
    return table.concat(strings, ", ")
end

function getTitle(form, base_name, name, suffix, short)
    if form.seasonal then
        if short then
            if form.season_suffix == false then
                return nil
            end
            if form.season_suffix then
                return form.season_suffix
            end
            local season = getFirstSeason(form.season) or "" -- string.match(form.season, "(.*) 20%d%d") or form.season
            local suffixInSeason = string.find(season, suffix)
            local seasonInSuffix = string.find(suffix, season)
            if suffixInSeason then
                return name ~= base_name and name
            elseif seasonInSuffix then
                return string.sub(suffix, 1, seasonInSuffix - 2)
            else
                return name == base_name and suffix or name .. " " .. suffix
            end
        else
            return name == base_name and suffix or name .. " " .. suffix
        end
    else
        return suffix ~= "" and suffix or name == base_name and "Base" or name
    end
end

local blur_options = [=[<div style="margin-top:5px;text-align:right">
<div class="toggle" data-target="nsfw" data-default="hide" data-classes="blur">
<span class="toggle-show" style="cursor:pointer;color:#006cb0;">☑ Blur NSFW CG</span>
<span class="toggle-hide" style="cursor:pointer;color:#006cb0;">☒ Blur NSFW CG</span>
</div>
<div class="toggle" data-target="nsfw-damaged" data-default="hide" data-classes="blur">
<span class="toggle-show" style="cursor:pointer;color:#006cb0;">☑ Blur other damaged CG</span>
<span class="toggle-hide" style="cursor:pointer;color:#006cb0;">☒ Blur other damaged CG</span>
</div>
</div>]=]

function ShipPage.Gallery(frame, args)
    args = args or U.getTemplateArgs(frame)
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local forms = ship_cgs(ship_name)
    local result = { '<div class="ship-gallery-page">' }
    local first_seasonal
    for _, form in ipairs(forms) do
        local name, suffix = Ship:process_ship_key(form.name)
        suffix = suffix or ""
        local title = getTitle(form, ship_name, name, suffix, true)
        if not first_seasonal and form.seasonal then
            first_seasonal = true
            table.insert(result, "<h2>[[Seasonal]]s</h2>")
        end
        if form.seasonal and (form.normal or form.damaged) then
            if form.season and not title then
                table.insert(result, format{
                    "<h3>${seasons}</h3>",
                    seasons = formatSeason(form.season)
                })
            elseif form.season then
                table.insert(result, format{
                    "<h3>${seasons} (${title})</h3>",
                    title = title,
                    seasons = formatSeason(form.season)
                })
            else
                table.insert(result, "<h3>" .. title .. "</h3>")
            end
        elseif form.normal or form.damaged then
            table.insert(result, "<h2>" .. title .. "</h2>")
        end
        table.insert(result, '<div class="ship-gallery-page-section">')
        if form.normal then
            table.insert(result, '<div class="ship-gallery-page-section-image">')
            table.insert(result, cg(form.seasonal, form.name))
            table.insert(result, "</div>")
        end
        if form.damaged then
            table.insert(result, '<div class="ship-gallery-page-section-image">')
            table.insert(result, cg(form.seasonal, form.name, true))
            table.insert(result, "</div>")
        end
        table.insert(result, "</div>")
    end
    table.insert(result, "</div>")
    table.insert(result, blur_options)
    return table.concat(result, "\n")
end

function ShipPage.GalleryTabber(args)
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local forms = ship_cgs(ship_name)
    local result = { "{{#tag:tabber|" }
    for _, form in ipairs(forms) do
        if form.normal or form.damaged then
            local name, suffix = Ship:process_ship_key(form.name)
            suffix = suffix or ""
            local title = getTitle(form, ship_name, name, suffix)
            table.insert(result, "{{!}}-{{!}}" .. title .. "=")
            if form.normal and form.damaged then
                local image = cg(form.seasonal, form.name, false, "300px", form.battle_card or not form.seasonal)
                local image_damaged = cg(form.seasonal, form.name, true, "300px", form.battle_card or not form.seasonal)
                table.insert(result, format{
                    ShipPage._gallery_tabber,
                    image = image,
                    image_damaged = image_damaged
                })
            elseif form.normal then
                local image = cg(form.seasonal, form.name, false, "300px", form.battle_card or not form.seasonal)
                table.insert(result, format{
                    ShipPage._gallery_normal,
                    image = image,
                })
            elseif form.damaged then
                local image_damaged = cg(form.seasonal, form.name, true, "300px", form.battle_card or not form.seasonal)
                table.insert(result, format{
                    ShipPage._gallery_damaged,
                    image = image_damaged,
                })
            end
        end
    end
    table.insert(result, "}}")
    table.insert(result, blur_options)
    return table.concat(result, "\n")
end

function ShipPage.BreakInstance(frame)
    local args = U.getTemplateArgs(frame)
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    local forms = ship_cgs(ship_name)
    return "<pre>\n" .. U.js(Ship(ship_name)) .. "\n</pre>"
end

function ShipPage.FooterSections(frame)
    local args = U.getTemplateArgs(frame)
    local ship_name = args.explicit.ship or args.implicit.pagename or ""
    return format{
        ShipPage._footer_sections,
        name = ship_name,
        gallery = frame:preprocess(ShipPage.GalleryTabber(args)),
        links = ShipPage.FooterLinks(args)
    }
end

return ShipPage