-- Sets up and returns coordinates for all possible spawn zones. Because Lua assigns tables by reference
-- and there is no built-in function to copy a table this is relatively brute force.
--
-- Positions are all relative to the player mat, and most are consistent. The
-- exception are the SetAside# zones, which are placed to the left of the mat
-- for White/Green, and the right of the mat for Orange/Red.
--
-- Investigator: Investigator card area.
-- Minicard: Placement for the investigator's minicard, just above the player mat
-- Deck, Discard: Standard locations for the deck and discard piles.
-- BlankTop: used for assets that start in play (e.g. Duke)
-- Tarot, Hand1, Hand2, Ally, BlankBottom, Accessory, Arcane1, Arcane2, Body: Asset slot positions
-- Threat[1-4]: Threat area slots. Threat[1-3] correspond to the named threat area slots, and Threat4 is the blank threat area slot.
-- SetAside[1-3]: Column closest to the player mat, with 1 at the top and 3 at the bottom.
-- SetAside[4-6]: Column farther away from the mat, with 4 at the top and 6 at the bottom.
-- SetAside1: Permanent cards
-- SetAside2: Bonded cards
-- SetAside3: Ancestral Knowledge / Underworld Market
-- SetAside4: Upgrade sheets for customizable cards
-- SetAside5: Hunch Deck for Joe Diamond
-- SetAside6: currently unused
do
  local Zones = { }

  local playerMatGuids     = {}
  playerMatGuids["Red"]    = "0840d5"
  playerMatGuids["Orange"] = "bd0ff4"
  playerMatGuids["White"]  = "8b081b"
  playerMatGuids["Green"]  = "383d8b"

  local commonZones                 = {}
  commonZones["Investigator"] = { -1.17702, 0, 0.00209 }
  commonZones["Minicard"]     = { -0.16, 0, -1.222326 }
  commonZones["Deck"]         = { -1.822724, 0, -0.02940192 }
  commonZones["Discard"]      = { -1.822451, 0, 0.6092291 }
  commonZones["Ally"]         = { -0.6157398, 0, 0.02435675 }
  commonZones["Body"]         = { -0.6306521, 0, 0.553170 }
  commonZones["Hand1"]        = { 0.2155387, 0, 0.04257287 }
  commonZones["Hand2"]        = { -0.1803701, 0, 0.03745948 }
  commonZones["Arcane1"]      = { 0.2124223, 0, 0.5596902 }
  commonZones["Arcane2"]      = { -0.1711275, 0, 0.5567944 }
  commonZones["Tarot"]        = { 0.6016169, 0, 0.03273106 }
  commonZones["Accessory"]    = { 0.6049907, 0, 0.5546234 }
  commonZones["BlankTop"]     = { 1.758446, 0, 0.03965336 }
  commonZones["BlankBottom"]  = { 1.754469, 0, 0.5634764 }
  commonZones["Threat1"]      = { -0.9116555, 0, -0.6446251 }
  commonZones["Threat2"]      = { -0.4544126, 0, -0.6428719 }
  commonZones["Threat3"]      = { 0.002246313, 0, -0.6430681 }
  commonZones["Threat4"]      = { 0.4590618, 0, -0.6432732 }

  local zoneData                            = {}
  zoneData["White"]                   = {}
  zoneData["White"]["Investigator"]   = commonZones["Investigator"]
  zoneData["White"]["Minicard"]       = commonZones["Minicard"]
  zoneData["White"]["Deck"]           = commonZones["Deck"]
  zoneData["White"]["Discard"]        = commonZones["Discard"]
  zoneData["White"]["Ally"]           = commonZones["Ally"]
  zoneData["White"]["Body"]           = commonZones["Body"]
  zoneData["White"]["Hand1"]          = commonZones["Hand1"]
  zoneData["White"]["Hand2"]          = commonZones["Hand2"]
  zoneData["White"]["Arcane1"]        = commonZones["Arcane1"]
  zoneData["White"]["Arcane2"]        = commonZones["Arcane2"]
  zoneData["White"]["Tarot"]          = commonZones["Tarot"]
  zoneData["White"]["Accessory"]      = commonZones["Accessory"]
  zoneData["White"]["BlankTop"]       = commonZones["BlankTop"]
  zoneData["White"]["BlankBottom"]    = commonZones["BlankBottom"]
  zoneData["White"]["Threat1"]        = commonZones["Threat1"]
  zoneData["White"]["Threat2"]        = commonZones["Threat2"]
  zoneData["White"]["Threat3"]        = commonZones["Threat3"]
  zoneData["White"]["Threat4"]        = commonZones["Threat4"]
  zoneData["White"]["SetAside1"]      = { 2.345893, 0, -0.520315 }
  zoneData["White"]["SetAside2"]      = { 2.345893, 0, 0.042552 }
  zoneData["White"]["SetAside3"]      = { 2.345893, 0, 0.605419 }
  zoneData["White"]["UnderSetAside3"] = { 2.495893, 0, 0.805419 }
  zoneData["White"]["SetAside4"]      = { 2.775893, 0, -0.520315 }
  zoneData["White"]["SetAside5"]      = { 2.775893, 0, 0.042552 }
  zoneData["White"]["SetAside6"]      = { 2.775893, 0, 0.605419 }
  zoneData["White"]["UnderSetAside6"] = { 2.925893, 0, 0.805419 }

  zoneData["Orange"]                   = {}
  zoneData["Orange"]["Investigator"]   = commonZones["Investigator"]
  zoneData["Orange"]["Minicard"]       = commonZones["Minicard"]
  zoneData["Orange"]["Deck"]           = commonZones["Deck"]
  zoneData["Orange"]["Discard"]        = commonZones["Discard"]
  zoneData["Orange"]["Ally"]           = commonZones["Ally"]
  zoneData["Orange"]["Body"]           = commonZones["Body"]
  zoneData["Orange"]["Hand1"]          = commonZones["Hand1"]
  zoneData["Orange"]["Hand2"]          = commonZones["Hand2"]
  zoneData["Orange"]["Arcane1"]        = commonZones["Arcane1"]
  zoneData["Orange"]["Arcane2"]        = commonZones["Arcane2"]
  zoneData["Orange"]["Tarot"]          = commonZones["Tarot"]
  zoneData["Orange"]["Accessory"]      = commonZones["Accessory"]
  zoneData["Orange"]["BlankTop"]       = commonZones["BlankTop"]
  zoneData["Orange"]["BlankBottom"]    = commonZones["BlankBottom"]
  zoneData["Orange"]["Threat1"]        = commonZones["Threat1"]
  zoneData["Orange"]["Threat2"]        = commonZones["Threat2"]
  zoneData["Orange"]["Threat3"]        = commonZones["Threat3"]
  zoneData["Orange"]["Threat4"]        = commonZones["Threat4"]
  zoneData["Orange"]["SetAside1"]      = { -2.350362, 0, -0.520315 }
  zoneData["Orange"]["SetAside2"]      = { -2.350362, 0, 0.042552 }
  zoneData["Orange"]["SetAside3"]      = { -2.350362, 0, 0.605419 }
  zoneData["Orange"]["UnderSetAside3"] = { -2.500362, 0, 0.80419 }
  zoneData["Orange"]["SetAside4"]      = { -2.7803627, 0, -0.520315 }
  zoneData["Orange"]["SetAside5"]      = { -2.7803627, 0, 0.042552 }
  zoneData["Orange"]["SetAside6"]      = { -2.7803627, 0, 0.605419 }
  zoneData["Orange"]["UnderSetAside6"] = { -2.9303627, 0, 0.80419 }

  -- Green positions are the same as White and Red the same as Orange
  zoneData["Red"] = zoneData["Orange"]
  zoneData["Green"] = zoneData["White"]

  -- Gets the global position for the given zone on the specified player mat.
  ---@param playerColor: Color name of the player mat to get the zone position for (e.g. "Red")
  ---@param zoneName: Name of the zone to get the position for.  See Zones object documentation for a list of valid zones.
  ---@return: Global position table, or nil if an invalid player color or zone is specified
  Zones.getZonePosition = function(playerColor, zoneName)
    if (playerColor ~= "Red"
        and playerColor ~= "Orange"
        and playerColor ~= "White"
        and playerColor ~= "Green") then
      return nil
    end
    return getObjectFromGUID(playerMatGuids[playerColor]).positionToWorld(zoneData[playerColor][zoneName])
  end

  -- Return the global rotation for a card on the given player mat, based on its metadata.
  ---@param playerColor: Color name of the player mat to get the rotation for (e.g. "Red")
  ---@param cardMetadata: Table of card metadata. Metadata fields type and permanent are required; all others are optional.
  ---@return: Global rotation vector for the given card. This will include the
  --     Y rotation to orient the card on the given player mat as well as a
  --     Z rotation to place the card face up or face down.
  Zones.getDefaultCardRotation = function(playerColor, zone)
    local deckRotation = getObjectFromGUID(playerMatGuids[playerColor]).getRotation()

    if zone == "Deck" then
      deckRotation = deckRotation + Vector(0, 0, 180)
    end

    return deckRotation
  end

  return Zones
end