-- Shopkeeper UI Functions File
-- Last Updated August 10, 2014
-- Written August 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
-- Released under terms in license accompanying this file.
-- Distribution without license is prohibited!

-- Handle the OnMoveStop event for the windows
function Shopkeeper.OnWindowMoveStop()
  Shopkeeper.savedVariables.winLeft = ShopkeeperWindow:GetLeft()
  Shopkeeper.savedVariables.winTop = ShopkeeperWindow:GetTop()
  Shopkeeper.savedVariables.miniWinLeft = ShopkeeperMiniWindow:GetLeft()
  Shopkeeper.savedVariables.miniWinTop = ShopkeeperMiniWindow:GetTop()
end

function Shopkeeper.OnStatsWindowMoveStop()
  Shopkeeper.savedVariables.statsWinLeft = ShopkeeperStatsWindow:GetLeft()
  Shopkeeper.savedVariables.statsWinTop = ShopkeeperStatsWindow:GetTop()
end

-- Restore the window positions from saved vars
function Shopkeeper:RestoreWindowPosition()
  local left = self.savedVariables.winLeft
  local top = self.savedVariables.winTop
  local statsLeft = self.savedVariables.statsWinLeft
  local statsTop = self.savedVariables.statsWinTop
  local miniLeft = self.savedVariables.miniWinLeft
  local miniTop = self.savedVariables.miniWinTop

  ShopkeeperWindow:ClearAnchors()
  ShopkeeperStatsWindow:ClearAnchors()
  ShopkeeperMiniWindow:ClearAnchors()
  ShopkeeperWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
  ShopkeeperStatsWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, statsLeft, statsTop)
  ShopkeeperMiniWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, miniLeft, miniTop)
end

-- Handle the changing of window font settings
function Shopkeeper:UpdateFonts()
  local LMP = LibStub("LibMediaProvider-1.0")
  if LMP then
    local font = LMP:Fetch('font', Shopkeeper.savedVariables.windowFont)
    local fontString = font .. "|%d"
    ShopkeeperWindowSearchLabel:SetFont(string.format(fontString, 16))
    ShopkeeperWindowSearchBox:SetFont(string.format(fontString, 16))
    ShopkeeperWindowTitle:SetFont(string.format(fontString, 26))
    ShopkeeperWindowBuyer:SetFont(string.format(fontString, 20))
    ShopkeeperWindowGuild:SetFont(string.format(fontString, 20))
    ShopkeeperWindowItemName:SetFont(string.format(fontString, 20))
    ShopkeeperWindowSellTime:SetFont(string.format(fontString, 20))
    ShopkeeperWindowPrice:SetFont(string.format(fontString, 20))
    ShopkeeperSwitchViewButton:SetFont(string.format(fontString, 16))
    ShopkeeperPriceSwitchButton:SetFont(string.format(fontString, 16))
    ShopkeeperResetButton:SetFont(string.format(fontString, 16))
    ShopkeeperRefreshButton:SetFont(string.format(fontString, 16))
    ShopkeeperMiniWindowSearchLabel:SetFont(string.format(fontString, 12))
    ShopkeeperMiniWindowSearchBox:SetFont(string.format(fontString, 12))
    ShopkeeperMiniWindowTitle:SetFont(string.format(fontString, 20))
    ShopkeeperMiniWindowGuild:SetFont(string.format(fontString, 16))
    ShopkeeperMiniWindowItemName:SetFont(string.format(fontString, 16))
    ShopkeeperMiniWindowSellTime:SetFont(string.format(fontString, 16))
    ShopkeeperMiniWindowPrice:SetFont(string.format(fontString, 16))
    ShopkeeperMiniSwitchViewButton:SetFont(string.format(fontString, 12))
    ShopkeeperMiniPriceSwitchButton:SetFont(string.format(fontString, 12))
    ShopkeeperMiniResetButton:SetFont(string.format(fontString, 12))
    ShopkeeperMiniRefreshButton:SetFont(string.format(fontString, 12))

    ShopkeeperStatsWindowTitle:SetFont(string.format(fontString, 26))
    ShopkeeperStatsWindowItemsSoldLabel:SetFont(string.format(fontString, 18))
    ShopkeeperStatsWindowTotalGoldLabel:SetFont(string.format(fontString, 18))
    ShopkeeperStatsWindowBiggestSaleLabel:SetFont(string.format(fontString, 18))
    ShopkeeperStatsWindowSliderSettingLabel:SetFont(string.format(fontString, 18))
    ShopkeeperStatsWindowSliderLabel:SetFont(string.format(fontString, 16))

    for i = 1, #Shopkeeper.DataRows do
      local dataRow = Shopkeeper.DataRows[i]
      dataRow:GetNamedChild("Buyer"):SetFont(string.format(fontString, 16))
      dataRow:GetNamedChild("Guild"):SetFont(string.format(fontString, 16))
      dataRow:GetNamedChild("ItemName"):SetFont(string.format(fontString, 16))
      dataRow:GetNamedChild("Quantity"):SetFont(string.format(fontString, 16))
      dataRow:GetNamedChild("SellTime"):SetFont(string.format(fontString, 16))
      dataRow:GetNamedChild("Price"):SetFont(string.format(fontString, 16))
      if i <= #Shopkeeper.MiniDataRows then
        local miniDataRow = Shopkeeper.MiniDataRows[i]
        miniDataRow:GetNamedChild("Guild"):SetFont(string.format(fontString, 12))
        miniDataRow:GetNamedChild("ItemName"):SetFont(string.format(fontString, 12))
        miniDataRow:GetNamedChild("Quantity"):SetFont(string.format(fontString, 12))
        miniDataRow:GetNamedChild("SellTime"):SetFont(string.format(fontString, 12))
        miniDataRow:GetNamedChild("Price"):SetFont(string.format(fontString, 12))
      end
    end
  end
end

-- Item tooltips
function Shopkeeper:ShowToolTip(itemName, itemButton)
  InitializeTooltip(ItemTooltip, itemButton)
  ItemTooltip:SetLink(itemName)
end

-- Clear a given row's data
function Shopkeeper.ClearDataRow(index)
  if index < 1 or index > 15 then
    return
  end

  local dataRow = Shopkeeper.DataRows[index]
  dataRow:GetNamedChild("Buyer"):SetText("")
  dataRow:GetNamedChild("Buyer"):SetHandler("OnMouseDoubleClick", nil)
  dataRow:GetNamedChild("Guild"):SetText("")
  dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
  dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
  local itemCell = dataRow:GetNamedChild("ItemName")
  itemCell:SetText("")
  itemCell:SetHandler("OnMouseDoubleClick", nil)
  itemCell:SetHandler("OnMouseEnter", nil)
  dataRow:GetNamedChild("Quantity"):SetText("")
  dataRow:GetNamedChild("SellTime"):SetText("")
  dataRow:GetNamedChild("Price"):SetText("")
end

function Shopkeeper.ClearMiniDataRow(index)
  if index < 1 or index > 8 then
    return
  end

  local dataRow = Shopkeeper.MiniDataRows[index]
  dataRow:GetNamedChild("Guild"):SetText("")
  dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
  dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
  local itemCell = dataRow:GetNamedChild("ItemName")
  itemCell:SetText("")
  itemCell:SetHandler("OnMouseDoubleClick", nil)
  itemCell:SetHandler("OnMouseEnter", nil)
  dataRow:GetNamedChild("Quantity"):SetText("")
  dataRow:GetNamedChild("SellTime"):SetText("")
  dataRow:GetNamedChild("Price"):SetText("")
end

-- Fill out a row with the given data
function Shopkeeper.SetDataRow(index, buyer, guild, itemName, icon, quantity, sellTime, price, seller, kioskSale)
  if index < 1 or index > 15 then return end

  local dataRow = Shopkeeper.DataRows[index]

  -- Some extra stuff for the Buyer cell to handle double-click and color changes
  -- Plus add a marker if buyer is not in-guild (kiosk sale)
  local buyerCell = dataRow:GetNamedChild("Buyer")
  local buyerString = buyer
  if kioskSale ~= nil and kioskSale == true then
    buyerString = "|t16:16:/EsoUI/Art/icons/item_generic_coinbag.dds|t" .. buyerString
  end
  buyerCell:SetText(buyerString)
  -- If the seller is the player, color the buyer green.  Otherwise, blue.
  local acctName = GetDisplayName()
  if seller == acctName then
    buyerCell:SetNormalFontColor(0.18, 0.77, 0.05, 1)
    buyerCell:SetPressedFontColor(0.18, 0.77, 0.05, 1)
    buyerCell:SetMouseOverFontColor(0.32, 0.90, 0.18, 1)
  else
    buyerCell:SetNormalFontColor(0.21, 0.54, 0.94, 1)
    buyerCell:SetPressedFontColor(0.21, 0.54, 0.94, 1)
    buyerCell:SetMouseOverFontColor(0.34, 0.67, 1, 1)
  end
  buyerCell:SetHandler("OnMouseDoubleClick", function()
    if SCENE_MANAGER.currentScene.name == "mailSend" then
      ZO_MailSendToField:SetText("")
      ZO_MailSendToField:SetText(ZO_MailSendToField:GetText() .. buyer)
    else
      ZO_ChatWindowTextEntryEditBox:SetText("/w " .. buyer .. " " .. ZO_ChatWindowTextEntryEditBox:GetText())
    end
  end)
  local buyerCellLabel = buyerCell:GetLabelControl()
  buyerCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)

  -- Guild cell
  dataRow:GetNamedChild("Guild"):SetText(guild)
  local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
  guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)

  -- Item Icon
  dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
  dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)

  -- Item name cell
  local itemCell = dataRow:GetNamedChild("ItemName")
  itemCell:SetText(zo_strformat("<<t:1>>", itemName))
  -- Insert the item link into the chat box, with a quick substitution so brackets show up
  itemCell:SetHandler("OnMouseDoubleClick", function()
    ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
  end)
  itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
  itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
  local itemCellLabel = itemCell:GetLabelControl()
  itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)

  -- Quantity cell
  dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)

  -- Sale time cell
  dataRow:GetNamedChild("SellTime"):SetText(sellTime)

  -- Handle the setting of whether or not to show pre-cut sale prices
  -- math.floor(number + 0.5) is a quick shorthand way to round for
  -- positive values.
  local dispPrice = price
  if Shopkeeper.savedVariables.showFullPrice then
    if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
      dispPrice = math.floor((dispPrice / quantity) + 0.5)
    end
  else
    local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
    if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
      cutPrice = cutPrice / quantity
    end
    dispPrice = math.floor(cutPrice + 0.5)
  end

  -- Insert thousands separators for the price
  local stringPrice = Shopkeeper.localizedNumber(dispPrice)

  -- Finally, set the price
  dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
end

-- Fill out a row with the given data
function Shopkeeper.SetMiniDataRow(index, guild, itemName, icon, quantity, sellTime, price, seller)
  if index < 1 or index > 8 then return end

  local dataRow = Shopkeeper.MiniDataRows[index]

  -- Guild cell
  dataRow:GetNamedChild("Guild"):SetText(guild)
  local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
  guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)

  -- Item Icon
  dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
  dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)

  -- Item name cell
  local itemCell = dataRow:GetNamedChild("ItemName")
  itemCell:SetText(zo_strformat("<<t:1>>", itemName))
  -- Insert the item link into the chat box, with a quick substitution so brackets show up
  itemCell:SetHandler("OnMouseDoubleClick", function()
    ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
  end)
  itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
  itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
  local itemCellLabel = itemCell:GetLabelControl()
  itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)

  -- Quantity cell
  dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)

  -- Sale time cell
  dataRow:GetNamedChild("SellTime"):SetText(sellTime)

  -- Handle the setting of whether or not to show pre-cut sale prices
  -- math.floor(number + 0.5) is a quick shorthand way to round for
  -- positive values.
  local dispPrice = price
  if Shopkeeper.savedVariables.showFullPrice then
    if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
      dispPrice = math.floor((dispPrice / quantity) + 0.5)
    end
  else
    local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
    if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
      cutPrice = cutPrice / quantity
    end
    dispPrice = math.floor(cutPrice + 0.5)
  end

  -- Insert thousands separators for the price
  local stringPrice = Shopkeeper.localizedNumber(dispPrice)

  -- Finally, set the price
  dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
end

-- Build the data rows based on the position of the slider
function Shopkeeper.DisplayRows()
  if Shopkeeper.savedVariables.viewSize == "full" then
    local startIndex = ShopkeeperWindowSlider:GetValue()
    if startIndex + #Shopkeeper.DataRows > #Shopkeeper.SearchTable then
      startIndex = #Shopkeeper.SearchTable - #Shopkeeper.DataRows
    end

    if startIndex < 1 then startIndex = 0 end

    -- Hide the slider if there's less than a full page of results
    ShopkeeperWindowSlider:SetHidden(#Shopkeeper.SearchTable < 16)

    for i = 1, #Shopkeeper.DataRows do
      local rowIndex = i + startIndex
      if rowIndex > #Shopkeeper.SearchTable then
        Shopkeeper.ClearDataRow(i)
        ShopkeeperWindowSlider:SetHidden(true)
      else
        local scanResult = Shopkeeper.SearchTable[rowIndex]
        -- Older data won't have kiosk info
        local kioskSale = nil
        if #scanResult > 8 then kioskSale = scanResult[9] end
        Shopkeeper.SetDataRow(i, scanResult[1], scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8], kioskSale)
      end
    end

    -- Scale the slider's range to the number of items we have minus the number of rows
    local sliderMax = 0
    local tableToUse = Shopkeeper.ScanResults
    if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
    if #tableToUse > 15 then sliderMax = (#tableToUse - 15) end
    ShopkeeperWindowSlider:SetMinMax(0, sliderMax)
  else
    local startIndex = ShopkeeperMiniWindowSlider:GetValue()
    if startIndex + #Shopkeeper.MiniDataRows > #Shopkeeper.SearchTable then
      startIndex = #Shopkeeper.SearchTable - #Shopkeeper.MiniDataRows
    end

    if startIndex < 1 then startIndex = 0 end

    -- Hide the slider if there's less than a full page of results
    ShopkeeperMiniWindowSlider:SetHidden(#Shopkeeper.SearchTable < 9)

    for i = 1, #Shopkeeper.MiniDataRows do
      local rowIndex = i + startIndex
      if rowIndex > #Shopkeeper.SearchTable then
        Shopkeeper.ClearMiniDataRow(i)
        ShopkeeperMiniWindowSlider:SetHidden(true)
      else
        local scanResult = Shopkeeper.SearchTable[rowIndex]
        Shopkeeper.SetMiniDataRow(i, scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8])
      end
    end

    -- Scale the slider's range to the number of items we have minus the number of rows
    local sliderMax = 0
    local tableToUse = Shopkeeper.ScanResults
    if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
    if #tableToUse > 8 then sliderMax = (#tableToUse - 8) end
    ShopkeeperMiniWindowSlider:SetMinMax(0, sliderMax)
  end
end

function Shopkeeper.ToggleViewMode()
  if Shopkeeper.savedVariables.viewSize == "full" then
    Shopkeeper.savedVariables.viewSize = "half"
    ShopkeeperWindow:SetHidden(true)
    Shopkeeper.DisplayRows()
    ShopkeeperMiniWindow:SetHidden(false)

    if Shopkeeper.savedVariables.openWithMail then
      MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.uiFragment)
      MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.uiFragment)
      MAIL_INBOX_SCENE:AddFragment(Shopkeeper.miniUiFragment)
      MAIL_SEND_SCENE:AddFragment(Shopkeeper.miniUiFragment)
    end

    if Shopkeeper.savedVariables.openWithStore then
      TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.uiFragment)
      TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.miniUiFragment)
    end
  else
    Shopkeeper.savedVariables.viewSize = "full"
    ShopkeeperMiniWindow:SetHidden(true)
    Shopkeeper.DisplayRows()
    ShopkeeperWindow:SetHidden(false)

    if Shopkeeper.savedVariables.openWithMail then
      MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
      MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
      MAIL_INBOX_SCENE:AddFragment(Shopkeeper.uiFragment)
      MAIL_SEND_SCENE:AddFragment(Shopkeeper.uiFragment)
    end

    if Shopkeeper.savedVariables.openWithStore then
      TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
      TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.uiFragment)
    end
  end
end

-- Set the visibility status of the main window to the opposite of its current status
function Shopkeeper.ToggleShopkeeperWindow()
  if Shopkeeper.savedVariables.viewSize == "full" then
    ShopkeeperMiniWindow:SetHidden(true)
    if ShopkeeperWindow:IsHidden() then
      Shopkeeper.DisplayRows()
      SetGameCameraUIMode(true)
    end

    ShopkeeperWindow:SetHidden(not ShopkeeperWindow:IsHidden())
  else
    ShopkeeperWindow:SetHidden(true)
    if ShopkeeperMiniWindow:IsHidden() then
      Shopkeeper.DisplayRows()
      SetGameCameraUIMode(true)
    end

    ShopkeeperMiniWindow:SetHidden(not ShopkeeperMiniWindow:IsHidden())
  end
end

-- Set the visibility status of the stats window to the opposite of its current status
function Shopkeeper.ToggleShopkeeperStatsWindow()
  if ShopkeeperStatsWindow:IsHidden() then Shopkeeper.UpdateStatsWindow() end
  ShopkeeperStatsWindow:SetHidden(not ShopkeeperStatsWindow:IsHidden())
end

-- Handle scrolling the main window
function Shopkeeper.OnSliderMouseWheel(self, delta)
  if Shopkeeper.savedVariables.viewSize == "full" then
    local oldSliderLevel = ShopkeeperWindowSlider:GetValue()
    local newSliderLevel = oldSliderLevel - delta
    ShopkeeperWindowSlider:SetValue(newSliderLevel)
  else
    local oldSliderLevel = ShopkeeperMiniWindowSlider:GetValue()
    local newSliderLevel = oldSliderLevel - delta
    ShopkeeperMiniWindowSlider:SetValue(newSliderLevel)
  end
end

-- Update the table if the slider moved
function Shopkeeper.OnSliderMoved(self, sliderLevel, eventReason)
  Shopkeeper.DisplayRows()
end

function Shopkeeper.OnStatsSliderMoved(self, sliderLevel, eventReason)
  Shopkeeper.UpdateStatsWindow()
end