FtFarmer = ZO_Object:Subclass()
local fm = FarmManager

local function GetDisplayName(memberName)
    for guildIndex = 1, GetNumGuilds() do
        local guildId = GetGuildId(guildIndex)
        for memberIndex = 1, GetNumGuildMembers(guildId) do
            local hasChar, characterName = GetGuildMemberCharacterInfo(guildId, memberIndex)
            if hasChar then
                characterName = zo_strformat(SI_UNIT_NAME, characterName)
                if characterName == memberName then
                    local account = GetGuildMemberInfo(guildId, memberIndex)
                    return account
                end
            end
        end
    end
end

local function Sleep(s)
    local ntime = os.clock() + s
    repeat until os.clock() > ntime
end

local function GetEmptySlot(bagNumber)
    local sleepCount = 0
    local dest = nil
    while (dest == nil) and (sleepCount < 5) do
        dest = FindFirstEmptySlotInBag(bagNumber)
        if dest == nil then
            Sleep(2)
            sleepCount = sleepCount + 1
        end
    end
    return dest
end

function FtFarmer:New(memberName)
    local farmer = ZO_Object.New(self)
    farmer:Init(memberName)
    return farmer
end

function FtFarmer:Init(memberName)
    self.name = memberName
    self.displayName = GetDisplayName(memberName)
    self.itemsFarmed = ItemList:New()
    self.itemsDeposited = ItemList:New()
    self.timeStarted = GetTimeStamp()
    self.totalValueFarmed = 0
    self.totalValueDeposited = 0
    self.events = {}
    self.bag = BAG_DELETE

    self.secondsPaused = 0
    self.paused = false
    self.pausedTime = 0

end

function Farmer:Pause()
    if self.paused == true then
        self.paused = false
        timePassed = ((GetGameTimeMilliseconds() - self.pausedTime) / 1000)
        self.secondsPaused = self.pausedTime + timePassed
        self.pausedTime = 0
        d('Unpausing Farming Manager')
    else
        self.paused = true
        self.pausedTime = GetGameTimeMilliseconds()
        d('Pausing Farming Manager')

    end
end

function Farmer:Farm(itemLink, quantity)
    if self.paused == false then
        local item = self.itemsFarmed:Add(itemLink, quantity)
        self.totalValueFarmed = self.totalValueFarmed + (item.value * quantity)
        fm.window:OnItemFarmed(item, ACTION_FARM)
    else
        d('we are paused')
    end
end

function FtFarmer:ItemFilter(itemData)
    local item = self.itemsFarmed.items[itemData.slotIndex]
    return item ~= nil
end

function FtFarmer:MoveItemsToBackpack()
    local srcBag = BAG_VIRTUAL
    local manager = InventoryManager:New()
    local bagCache = SHARED_INVENTORY:GenerateFullSlotData(nil, srcBag)

    for _, data in pairs(bagCache) do
        local itemLink = GetItemLink(srcBag, data.slotIndex)
        local itemId = GetItemLinkItemId(itemLink)
        local item = self.itemsFarmed.items[itemId]
        if item ~= nil then
            manager:AddItemToBackpack(srcBag, data.slotIndex, item.quantity)
        end
    end
end

function FtFarmer:DepositItemsInBank()
    if self.bagId == BAG_DELETE then
        d("Must be at a bank to deposit")
        return
    end

    local srcBag = BAG_BACKPACK
    local manager = InventoryManager:New()
    local bagCache = SHARED_INVENTORY:GenerateFullSlotData(nil, srcBag)

    for _, data in pairs(bagCache) do
        local itemLink = GetItemLink(srcBag, data.slotIndex)
        local itemId = GetItemLinkItemId(itemLink)
        local item = self.itemsFarmed.items[itemId]
        if item ~= nil then
            manager:AddItemToBank(self.bagId, srcBag, data.slotIndex, item.quantity)
        end
    end
end

function FtFarmer:Deposit(itemLink, quantity)
    local item = self.itemsDeposited:Add(itemLink, quantity)
    self.totalValueDeposited = self.totalValueDeposited + (item.value * quantity)
    fm.window:OnItemFarmed(item, ACTION_DEPOSIT)
end

function FtFarmer:GetGoldPerSecond()
    if self.itemsFarmed.totalValue == 0 then return 0 end
    return self.itemsFarmed.totalValue / (GetTimeStamp() - self.timeStarted  - self.secondsPaused)
end

function FtFarmer:Reset()
    self:Init(self.name)
end