--[[ Copyright (c) 2009 Edvin "Lego3" Linge

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. --]]

--! Drug Casebook fullscreen window (view disease statistics and set prices).
class "UICasebook" (UIFullscreen)

---@type UICasebook
local UICasebook = _G["UICasebook"]

function UICasebook:UICasebook(ui, disease_selection)
  self:UIFullscreen(ui)
  local gfx = ui.app.gfx
  if not pcall(function()
    self.background = gfx:loadRaw("DrugN01V", 640, 480, "QData", "QData", "DrugN01V.pal")
    local palette = gfx:getPalette("DrugN01V.pal")
    self.panel_sprites = gfx:loadSpriteTable("QData", "DrugN02V", true, palette, { apply_ui_scale = true })
    self.title_font = gfx:loadFontAndSpriteTable("QData", "Font25V", false, palette, { apply_ui_scale = true })
    self.selected_title_font = gfx:loadFontAndSpriteTable("QData", "Font26V", false, palette, { apply_ui_scale = true })
    self.drug_font = gfx:loadFontAndSpriteTable("QData", "Font24V", false, palette, { apply_ui_scale = true })
  end) then
    ui:addWindow(UIInformation(ui, {_S.errors.dialog_missing_graphics}))
    self:close()
    return
  end

  self.ui = ui
  self.hospital = ui.hospital
  self.casebook = self.hospital.disease_casebook
  self:updateDiseaseList()

  -- Buttons
  self:addPanel(0, 607, 449):makeButton(0, 0, 26, 26, 3, self.close):setTooltip(_S.tooltip.casebook.close)
  self:addPanel(0, 439, 29):makeRepeatButton(0, 0, 70, 46, 1, self.scrollUp):setTooltip(_S.tooltip.casebook.up)
  self:addPanel(0, 437, 394):makeRepeatButton(0, 0, 77, 53, 2, self.scrollDown):setTooltip(_S.tooltip.casebook.down)
  self:addPanel(0, 354, 133):makeRepeatButton(0, 0, 22, 22, 5, self.increasePay):setTooltip(_S.tooltip.casebook.increase)
  self:addPanel(0, 237, 133):makeRepeatButton(0, 0, 22, 22, 4, self.decreasePay):setTooltip(_S.tooltip.casebook.decrease)
  self:addPanel(0, 235, 400):makeButton(0, 0, 140, 20, 0, self.concentrateResearch)
    :setTooltip(_S.tooltip.casebook.research)

  self:registerKeyHandlers();

  -- Icons representing cure effectiveness and other important information.
  self.machinery = self:addPanel(6, 306, 352):setTooltip(_S.tooltip.casebook.cure_type.machine)
  self.machinery.visible = false
  self.drug = self:addPanel(7, 306, 352):setDynamicTooltip(--[[persistable:casebook_drug_tooltip]] function()
    return _S.tooltip.casebook.cure_type.drug_percentage:format(self.casebook[self.selected_disease].cure_effectiveness)
  end)
  self.drug.visible = false
  self.surgery = self:addPanel(8, 306, 352):setTooltip(_S.tooltip.casebook.cure_type.surgery)
  self.surgery.visible = false
  self.unknown = self:addPanel(9, 306, 352):setTooltip(_S.tooltip.casebook.cure_type.unknown)
  self.unknown.visible = false
  self.psychiatry = self:addPanel(10, 306, 352):setTooltip(_S.tooltip.casebook.cure_type.psychiatrist)
  self.psychiatry.visible = false

  self.curable = self:addPanel(11, 335, 352):setTooltip(_S.tooltip.casebook.cure_requirement.possible)
  self.curable.visible = false
  self.not_curable = self:addPanel(12, 335, 352):setTooltip(_S.tooltip.casebook.cure_requirement.not_possible) -- TODO: split up in more specific requirements
  self.not_curable.visible = false

  self.percentage_counter = false -- Counter for displaying cure price percentage for a certain time before switching to price.

  self:makeTooltip(_S.tooltip.casebook.reputation,       249,  72, 362, 117)
  self:makeTooltip(_S.tooltip.casebook.treatment_charge, 249, 117, 362, 161)
  self:makeTooltip(_S.tooltip.casebook.earned_money,     247, 161, 362, 205)
  self:makeTooltip(_S.tooltip.casebook.cured,            247, 205, 362, 249)
  self:makeTooltip(_S.tooltip.casebook.deaths,           247, 249, 362, 293)
  self:makeTooltip(_S.tooltip.casebook.sent_home,        247, 293, 362, 337)

  if disease_selection then
    self:selectDisease(disease_selection)
  elseif self.ui.casebook_selected_disease then
    self:selectDisease(self.ui.casebook_selected_disease)
  else
    self.selected_index = #self.names_sorted
    self.selected_disease = self.names_sorted[self.selected_index]
    self:updateIcons()
  end
end

function UICasebook:registerKeyHandlers()
  -- Hotkeys
  self:addKeyHandler("ingame_scroll_up", self.scrollUp)
  self:addKeyHandler("ingame_scroll_down", self.scrollDown)
  self:addKeyHandler("ingame_scroll_left", self.decreasePay)
  self:addKeyHandler("ingame_scroll_right", self.increasePay)
end

function UICasebook:close()
  UIFullscreen.close(self)
  self.ui:getWindow(UIBottomPanel):updateButtonStates()
end

--! The diseases list has been changed, update the list.
function UICasebook:updateDiseaseList()
  -- A sorted list of known diseases and pseudo diseases.
  -- Used to be able to list the diseases in, believe it or not,
  -- alphabetical order.
  self.names_sorted = {}
  for n, value in pairs(self.casebook) do
    if value.discovered then
      self.names_sorted[#self.names_sorted + 1] = n
    end
  end
  table.sort(self.names_sorted, function(d1, d2)
    local c1, c2 = self.casebook[d1], self.casebook[d2]
    if c1.pseudo ~= c2.pseudo then
      return c1.pseudo
    end
    return c1.disease.name:upper() < c2.disease.name:upper()
  end)

  if self.selected_disease then -- Re-select the current disease.
    self:selectDisease(self.selected_disease)
  end
end

--! Select a disease by name.
--!param disease (string) Name of the disease
function UICasebook:selectDisease(disease)
  for i = 1, #self.names_sorted do
    if disease == self.names_sorted[i] then
      self.selected_index = i
      self.selected_disease = self.names_sorted[self.selected_index]
      break
    end
  end
  self:updateIcons()
end

--! Function that is called when a new entry is selected in some way
--! It updates all icons etc. that react to what is selected
function UICasebook:updateIcons()
  local disease = self.selected_disease
  local hosp = self.hospital

  local known = true
  -- Curable / not curable icons and their tooltip
  if self.casebook[disease].pseudo then
    self.curable.visible = false
    self.not_curable.visible = false
  else
    local req = hosp:checkDiseaseRequirements(disease)
    if not req then
      self.curable.visible = true
      self.not_curable.visible = false
    else
      self.curable.visible = false
      self.not_curable.visible = true

      -- Strings for the tooltip
      local research = false
      local build = false
      local staff = false
      -- Room requirements
      for _, room_id in ipairs(req.rooms) do
        -- Not researched yet?
        if not hosp:isRoomDiscovered(room_id) then
          known = false
          research = (research and (research .. ", ") or " (") .. TheApp.rooms[room_id].name
        end
        -- Researched, but not built. TODO: maybe make this an else clause to not oversize the tooltip that much
        build = (build and (build .. ", ") or " (") .. TheApp.rooms[room_id].name
      end
      research = research and (_S.tooltip.casebook.cure_requirement.research_machine .. research .. "). ") or ""
      build    = build    and (_S.tooltip.casebook.cure_requirement.build_room .. build .. "). ") or ""

      -- Staff requirements
      for sclass, amount in pairs(req.staff) do
        staff = (staff and (staff .. ", ") or " (") .. StaffProfile.translateStaffClass(sclass) .. ": " .. amount
      end
      staff = staff and (_S.tooltip.casebook.cure_requirement.hire_staff .. staff .. "). ") or ""

      self.not_curable:setTooltip(research .. build .. staff)
    end
  end

  self.unknown.visible    = not known
  self.drug.visible       = known and not not self.casebook[disease].drug
  self.machinery.visible  = known and not not self.casebook[disease].machine and not self.casebook[disease].pseudo
  self.psychiatry.visible = known and not not self.casebook[disease].psychiatrist
  self.surgery.visible    = known and not not self.casebook[disease].surgeon

  self.ui:updateTooltip() -- for the case that mouse is hovering over icon while player scrolls through list with keys
  self.percentage_counter = 50
  self.ui.casebook_selected_disease = disease
end

function UICasebook:draw(canvas, x, y)
  local s = TheApp.config.ui_scale
  canvas:scale(s, "bitmap")
  self.background:draw(canvas, self.x * s + x, self.y * s + y)
  canvas:scale(1, "bitmap")
  UIFullscreen.draw(self, canvas, x, y)

  x, y = self.x * s + x, self.y * s + y
  local titles = self.title_font
  local book = self.casebook
  local disease = self.selected_disease
  local selected = self.selected_index

  -- All titles
  titles:draw(canvas, _S.casebook.reputation,       x + 278 * s, y + 68 * s)
  titles:draw(canvas, _S.casebook.treatment_charge, x + 260 * s, y + 113 * s)
  titles:draw(canvas, _S.casebook.earned_money,     x + 265 * s, y + 157 * s)
  titles:draw(canvas, _S.casebook.cured,            x + 276 * s, y + 201 * s)
  titles:draw(canvas, _S.casebook.deaths,           x + 279 * s, y + 245 * s)
  titles:draw(canvas, _S.casebook.sent_home,        x + 270 * s, y + 289 * s)
  titles:draw(canvas, _S.casebook.cure,             x + 255 * s, y + 354 * s)

  -- Specific disease information
  if self.hospital:canConcentrateResearch(disease) then
    if book[disease].concentrate_research then  -- Concentrate research
      self.selected_title_font:draw(canvas, _S.casebook.research, x + 245 * s, y + 398 * s)
    else
      titles:draw(canvas, _S.casebook.research, x + 245 * s, y + 398 * s)
    end
  end
  local rep = book[disease].reputation or self.hospital.reputation
  if rep < self.hospital.reputation_min then
    rep = self.hospital.reputation_min
  elseif rep > self.hospital.reputation_max then
    rep = self.hospital.reputation_max
  end

  titles:draw(canvas, rep, x + 248 * s, y + 92 * s, 114 * s, 0) -- Reputation

  -- Treatment Charge is either displayed in percent, or normally
  local price_text = self.percentage_counter and ("%.0f%%"):format(book[disease].price * 100) or
      "$" .. self.hospital:getTreatmentPrice(disease)
  titles:draw(canvas, price_text, x + 262 * s, y + 137 * s, 90 * s, 0) -- Treatment Charge

  titles:draw(canvas, "$" .. book[disease].money_earned, x + 248 * s, y + 181 * s, 114 * s, 0) -- Money Earned
  titles:draw(canvas, book[disease].recoveries, x + 248 * s, y + 225 * s, 114 * s, 0) -- Recoveries
  titles:draw(canvas, book[disease].fatalities, x + 248 * s, y + 269 * s, 114 * s, 0) -- Fatalities
  titles:draw(canvas, book[disease].turned_away, x + 248 * s, y + 313 * s, 114 * s, 0) -- Turned away

  -- Cure percentage
  if self.drug.visible then
    self.drug_font:draw(canvas, book[disease].cure_effectiveness, x + 313 * s, y + 364 * s, 16 * s, 0)
  end
  -- Right-hand side list of diseases (and pseudo diseases)
  local index = 1
  while selected - index > 0 and index <= 7 do
    titles:draw(canvas, book[self.names_sorted[selected - index]].disease.name:upper(), x + 409 * s, y + 203 * s - index * 18 * s)
    index = index + 1
  end
  self.selected_title_font:draw(canvas, book[disease].disease.name:upper(), x + 409 * s, y + 227 * s)
  index = 1
  while index + selected <= #self.names_sorted and index <= 7 do
    titles:draw(canvas, book[self.names_sorted[index + selected]].disease.name:upper(), x + 409 * s, y + 251 * s + index * 18 * s)
    index = index + 1
  end
end

function UICasebook:scrollUp()
  if self.selected_index > 1 then
    if self.ui.app.key_modifiers.ctrl then
      self.selected_index = 1
    else
      self.selected_index = self.selected_index - 1
    end

    self.selected_disease = self.names_sorted[self.selected_index]
    self.ui:playSound("pagetur2.wav")
  else
    self.ui:playSound("Wrong2.wav")
  end
  self:updateIcons()
end

function UICasebook:scrollDown()
  if self.selected_index < #self.names_sorted then
    if self.ui.app.key_modifiers.ctrl then
      self.selected_index = #self.names_sorted
    else
      self.selected_index = self.selected_index + 1
    end

    self.selected_disease = self.names_sorted[self.selected_index]
    self.ui:playSound("pagetur2.wav")
  else
    self.ui:playSound("Wrong2.wav")
  end
  self:updateIcons()
end

function UICasebook:increasePay()
  local price = self.casebook[self.selected_disease].price
  local amount = 0.01
  if self.ui.app.key_modifiers.ctrl then
    amount = amount * 25
  elseif self.ui.app.key_modifiers.shift then
    amount = amount * 5
  end
  price = price + amount
  if price > 2 then
    price = 2
    self.ui:playSound("Wrong2.wav")
  else
    self.ui:playSound("selectx.wav")
  end
  self.casebook[self.selected_disease].price = price
  self.percentage_counter = 50
end

function UICasebook:decreasePay()
  local price = self.casebook[self.selected_disease].price
  local amount = 0.01
  if self.ui.app.key_modifiers.ctrl then
    amount = amount * 25
  elseif self.ui.app.key_modifiers.shift then
    amount = amount * 5
  end
  price = price - amount
  if price < 0.5 then
    price = 0.5
    self.ui:playSound("Wrong2.wav")
  else
    self.ui:playSound("selectx.wav")
  end
  self.casebook[self.selected_disease].price = price
  self.percentage_counter = 50
end

function UICasebook:concentrateResearch()
  if self.hospital:canConcentrateResearch(self.selected_disease) then
    self.hospital.research:concentrateResearch(self.selected_disease)
  end
end

function UICasebook:onMouseDown(button, x, y)
  local s = TheApp.config.ui_scale
  -- Normal window operations if outside the disease list
  if x < 395 * s or x > 540 * s or y < 77 * s or y > 394 * s then
    return UIFullscreen.onMouseDown(self, button, x, y)
  end

  local index_diff
  if y < 203 * s then
    index_diff = -7 + math.floor((y - (77 * s)) / (18 * s))
  elseif y > 269 * s then
    index_diff = math.floor((y - (269 * s)) / (18 * s)) + 1
  else
    return
  end

  -- Clicking on a disease name scrolls to the disease
  local new_index = self.selected_index + index_diff
  if new_index >= 1 and new_index <= #self.names_sorted then
    self.selected_index = new_index
    self.selected_disease = self.names_sorted[self.selected_index]
    self.ui:playSound("pagetur2.wav")
    self:updateIcons()
  end
end

function UICasebook:onMouseWheel(x, y)
  if not UIFullscreen.onMouseWheel(self, x, y) then
    if self:hitTest(self.cursor_x, self.cursor_y) then
      if y > 0 then
        self:scrollUp()
        return true
      else
        self:scrollDown()
        return true
      end
    end
    return false
  else
    return true
  end
end

function UICasebook:onTick()
  -- Decrease counter for showing percentage of cure price, if applicable
  if self.percentage_counter then
    self.percentage_counter = self.percentage_counter - 1
    if self.percentage_counter <= 0 then
      self.percentage_counter = false
    end
  end
  return UIFullscreen.onTick(self)
end

function UICasebook:afterLoad(old, new)
  if old < 236 then
    local gfx = TheApp.gfx
    self.background = gfx:loadRaw("DrugN01V", 640, 480, "QData", "QData", "DrugN01V.pal", true)
    local palette = gfx:getPalette("DrugN01V.pal")
    self.panel_sprites = gfx:loadSpriteTable("QData", "DrugN02V", true, palette, { apply_ui_scale = true })
    self.title_font = gfx:loadFontAndSpriteTable("QData", "Font25V", false, palette, { apply_ui_scale = true })
    self.selected_title_font = gfx:loadFontAndSpriteTable("QData", "Font26V", false, palette, { apply_ui_scale = true })
    self.drug_font = gfx:loadFontAndSpriteTable("QData", "Font24V", false, palette, { apply_ui_scale = true })
  end

  UIFullscreen.afterLoad(self, old, new)
  self:registerKeyHandlers()
end
