local c=require(script.Parent.Parent.TrelloHttp)local V=require(script.Parent.Parent.Commons)local l=require(script.Parent.Board)local z=V.generateMeta("\084\114\101\108\108\111\067\108\105\101\110\116")local H={}local function Q(c)local V=""if type(c)=="\116\097\098\108\101"then for l=1,#c-1,1 do V=V..(tostring(c[l]).."\044")end return V..tostring(c[#c])else return tostring(c)end end function H.new(V,H,S)if not V or V==""then error("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \089\111\117 \110\101\101\100 \097 \107\101\121 \116\111 \097\117\116\104\101\110\116\105\099\097\116\101 \121\111\117\114\115\101\108\102\033",0)end local i=S and error or warn local G="\107\101\121\061"..(V..((H and H~="")and"\038\116\111\107\101\110\061"..H or""))local N=false print("\104\116\116\112\115\058\047\047\097\112\105\046\116\114\101\108\108\111\046\099\111\109\047\049\047\109\101\109\098\101\114\115\047\109\101\063"..G)local Y if H and H~=""then Y=c.Request("\104\116\116\112\115\058\047\047\097\112\105\046\116\114\101\108\108\111\046\099\111\109\047\049\047\109\101\109\098\101\114\115\047\109\101\063"..G,c.HttpMethod.GET)else N=true Y=c.Request("\104\116\116\112\115\058\047\047\097\112\105\046\116\114\101\108\108\111\046\099\111\109\047\049\047\098\111\097\114\100\115\047\053\100\054\102\056\101\099\054\055\054\052\099\050\049\049\050\097\050\055\101\051\100\049\050\063"..G,c.HttpMethod.GET)end if not Y.LuaSuccess then error("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \070\097\116\097\108 \069\114\114\111\114 \104\097\115 \098\101\101\110 \116\104\114\111\119\110 \098\121 \072\116\116\112\083\101\114\118\105\099\101 \040"..(Y.SystemResponse.."\041\046"),0)else print("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \077\101\097\115\117\114\101\100 \076\097\116\101\110\099\121\058 "..(tostring(math.ceil(Y.Latency*1000)).."\109\115\046"))for c,V in pairs({5,3,2,1,.5})do if Y.Latency>=V then warn("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \065\080\073 \076\097\116\101\110\099\121 \105\115 \104\105\103\104\101\114 \116\104\097\110 "..(tostring(V*1000).."\109\115\033"))break end end if Y.StatusCode==200 then print("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \065\108\108 \079\075\046")elseif Y.StatusCode>=500 then i("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \066\097\100 \083\101\114\118\101\114 \082\101\115\112\111\110\115\101 - "..(tostring(Y.StatusCode).."\046 \083\101\114\118\105\099\101 \109\105\103\104\116 \098\101 \101\120\112\101\114\105\101\110\099\105\110\103 \105\115\115\117\101\115\046"))return nil elseif Y.StatusCode>=400 then i("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \066\097\100 \067\108\105\101\110\116 \082\101\113\117\101\115\116 - "..(tostring(Y.StatusCode).."\046 \067\104\101\099\107 \121\111\117\114 \097\117\116\104\101\110\116\105\099\097\116\105\111\110 \107\101\121\115\033"))return nil end end local t={}local j={}j.Auth=G j.User=Y.Body.fullName or""j._pkg={}function j._pkg.appendBoard(c)if t[c.RemoteId]then error("\068\117\112\108\105\099\097\116\101 \098\111\097\114\100 \105\100\033")end t[c.RemoteId]=c end function j._pkg.getBoards()return t end function j.MakeURL(l,c,V)if not c or c==""then error("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\077\097\107\101\085\082\076\093\058 \080\097\103\101 \097\114\103\117\109\101\110\116 \105\115 \101\109\112\116\121\033",0)end local z="\104\116\116\112\115\058\047\047\097\112\105\046\116\114\101\108\108\111\046\099\111\109\047\049\047"if c:sub(1,1)=="\047"then z=z..c:sub(2,-1)else z=z..c end if not V then return z..("\063"..l.Auth)end local H="\063"for c,V in pairs(V)do if type(c)~="\115\116\114\105\110\103"then error("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\077\097\107\101\085\082\076\093\058 \113\117\101\114\121\095\102\105\101\108\100\115 \109\117\115\116 \116\111 \098\101 \097 \100\105\099\116\105\111\110\097\114\121 \097\110\100 \097\108\108 \105\110\100\101\120\101\115 \109\117\115\116 \116\111 \098\101 \115\116\114\105\110\103\115\033",0)end if type(V)=="\116\097\098\108\101"and not V[1]then for V,l in pairs(V)do H=H..(c..("\047"..(V..("\061"..(Q(l).."\038")))))end else H=H..(c..("\061"..(Q(V).."\038")))end end return z..(H..l.Auth)end if N then print("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \065\100\100\101\100 \110\101\119 \117\115\101\114\108\101\115\115 \099\108\105\101\110\116\046")warn("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \084\104\105\115 \099\108\105\101\110\116 \099\097\110 \111\110\108\121 \114\101\097\100 \112\117\098\108\105\099 \098\111\097\114\100\115\046")else print("\091\084\114\101\108\108\111\067\108\105\101\110\116\046\110\101\119\093\058 \083\117\099\099\101\115\115\102\117\108\108\121 \097\117\116\104\101\110\116\105\099\097\116\101\100 \097\115 "..(j.User.."\046 \087\101\108\099\111\109\101\033"))local V=j:MakeURL("\047\109\101\109\098\101\114\115\047\109\101\047\098\111\097\114\100\115",{filter="\097\108\108",fields={"\105\100","\110\097\109\101";"\100\101\115\099\068\097\116\097","\099\108\111\115\101\100"};lists="\110\111\110\101";memberships="\110\111\110\101";organization=false})local z=c.RequestInsist(V,c.HttpMethod.GET,nil,true)for c in pairs(z)do t[c.id]=l.Make(c)end end return setmetatable(j,z)end return{Public=H}
--[[
    Name: Client.lua
    From roblox-trello v2

    Description: Constructor for Trello clients


    Copyright (c) 2019 Luis, David Duque

    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.
--]]

local HTTP = require(script.Parent.Parent.TrelloHttp)
local commons = require(script.Parent.Parent.Commons)
local Board = require(script.Parent.Board)

local TrelloClientMeta = commons.generateMeta("TrelloClient")

local TrelloClient = {}
local function toURL(value)
    local returns = ""

    if type(value) == "table" then
        for i = 1, #value - 1 do
            returns = returns .. tostring(value[i]) .. ","
        end
        return returns .. tostring(value[#value])
    else
        return tostring(value)
    end
end

--[[**
    Creates a new TrelloClient, that represents a Trello account.

    @param [t:String] key Your developer key. Cannot be empty or nil.
    @param [t:Variant<String,nil>] token Your developer token. Optional if you're only READING from a PUBLIC board.
    @param [t:Boolean] errorOnFailure Whether an error should be thrown (instead of a warning) if key validation fails.

    @returns [t:Variant<TrelloClient,nil>] A new TrelloClient, representing your account. Returns nil if key validation fails (with errorOnFailure disabled).
**--]]
function TrelloClient.new(key, token, errorOnFailure)
    if not key or key == "" then
        error("[TrelloClient.new]: You need a key to authenticate yourself!", 0)
    end

    local fail = errorOnFailure and error or warn

    local AUTH_STR = "key="..key..((token and token ~= "") and "&token="..token or "")
    local userless = false

    -- Perform authentication validation and assertation
    print("https://api.trello.com/1/members/me?" .. AUTH_STR)
    local dummyRequest
    if token and token ~= "" then
        dummyRequest = HTTP.Request("https://api.trello.com/1/members/me?" .. AUTH_STR, HTTP.HttpMethod.GET)
    else
        userless = true
        -- We don't have a particular user authenticated, so we'll resort to this - a public board.
        dummyRequest = HTTP.Request("https://api.trello.com/1/boards/5d6f8ec6764c2112a27e3d12?" .. AUTH_STR, HTTP.HttpMethod.GET)
    end

    if not dummyRequest.LuaSuccess then
        error("[TrelloClient.new]: Fatal Error has been thrown by HttpService (" .. dummyRequest.SystemResponse .. ").", 0)
    else
        print("[TrelloClient.new]: Measured Latency: " .. tostring(math.ceil(dummyRequest.Latency*1000)) .. "ms.")
        for _,l in pairs ({5, 3, 2, 1, 0.5}) do
            if dummyRequest.Latency >= l then
                warn("[TrelloClient.new]: API Latency is higher than " .. tostring(l*1000) .. "ms!")
                break
            end
        end

        if dummyRequest.StatusCode == 200 then
            print("[TrelloClient.new]: All OK.")
        elseif dummyRequest.StatusCode >= 500 then
            fail("[TrelloClient.new]: Bad Server Response - " .. tostring(dummyRequest.StatusCode) .. ". Service might be experiencing issues.")
            return nil
        elseif dummyRequest.StatusCode >= 400 then
            fail("[TrelloClient.new]: Bad Client Request - " .. tostring(dummyRequest.StatusCode) .. ". Check your authentication keys!")
            return nil
        end
    end

    -- All tests passed, we can make the TrelloClient.
    local localBoards = {}
    local trelloClient = {}
    trelloClient.Auth = AUTH_STR
    trelloClient.User = dummyRequest.Body.fullName or ""

    -- PACKAGE-PRIVATE METHODS - DO NOT USE
    trelloClient._pkg = {}

    function trelloClient._pkg.appendBoard(board)
        if localBoards[board.RemoteId] then
            error("Duplicate board id!")
        end

        localBoards[board.RemoteId] = board
    end

    function trelloClient._pkg.getBoards()
        return localBoards
    end

    -- PUBLIC METHODS

    --[[**
        Creates a syntactically correct URL for use within the module. Authentication is automatically appended.

        @param [t:String] page The page that you wish to request to. Base URL is https://api.trello.com/1/ (page cannot be empty).
        @param [t:Variant<Dictionary,nil>] query_fields A dictionary (indexes must to be strings) with any extra fields you want to query the API with.

        @returns [t:String] A URL string you can make requests to.
    **--]]
    function trelloClient:MakeURL(page, query_fields)
        if not page or page == "" then
            error("[TrelloClient.MakeURL]: Page argument is empty!", 0)
        end

        local newURL = "https://api.trello.com/1/"

        -- It's likely that we're going to mix '/page' with 'page' so better handle both cases
        if page:sub(1, 1) == "/" then
            newURL = newURL .. page:sub(2, -1)
        else
            newURL = newURL .. page
        end

        -- Tie the knot with the authentication and return
        if not query_fields then
            return newURL .. "?" .. self.Auth
        end

        -- Add query parameters and return
        local queryURL = "?"
        for field, value in pairs (query_fields) do
            if type(field) ~= "string" then
                error("[TrelloClient.MakeURL]: query_fields must to be a dictionary and all indexes must to be strings!", 0)
            end

            if type(value) == "table" and not value[1] then
                -- This is a dictionary
                for i, v in pairs(value) do
                    queryURL = queryURL .. field .. "/" .. i .. "=" .. toURL(v) .. "&"
                end
            else
                queryURL = queryURL .. field .. "=" .. toURL(value) .. "&"
            end
        end

        return newURL .. queryURL .. self.Auth
    end

    if userless then
        print("[TrelloClient.new]: Added new userless client.")
        warn("[TrelloClient.new]: This client can only read public boards.")
    else
        print("[TrelloClient.new]: Successfully authenticated as " .. trelloClient.User .. ". Welcome!")
        -- Fetch user's boards
        local fetchUrl = trelloClient:MakeURL("/members/me/boards", {
            filter = "all",
            fields = {"id", "name", "descData", "closed"},
            lists = "none",
            memberships = "none",
            organization = false
        })

        local boards = HTTP.RequestInsist(fetchUrl, HTTP.HttpMethod.GET, nil, true)

        for b in pairs(boards) do
            localBoards[b.id] = Board.Make(b)
        end

    end
    return setmetatable(trelloClient, TrelloClientMeta)
end

return {Public = TrelloClient}
