--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements.  See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License.  You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

--- @module swagger
-- Module for parsing swagger file

local _M = {}

-- Convert passed-in swagger body to valid lua table
-- @param swagger swagger file to parse
function _M.parseSwagger(swagger)
  local backends = parseBackends(swagger)
  local policies = parsePolicies(swagger)
  local security = parseSecurity(swagger)
  local corsObj = parseCors(swagger)
  local decoded = {
    name = swagger.info.title,
    basePath = swagger.basePath,
    resources = {}
  }
  for path, verbObj in pairs(swagger.paths) do
    decoded.resources[path] = { operations = {} }
    decoded.resources[path].cors = corsObj
    for verb, value in pairs(verbObj) do
      decoded.resources[path].operations[verb] = {}
      local verbObj = decoded.resources[path].operations[verb]
      if backends ~= nil then
        local backend = (backends["all"] ~= nil) and backends["all"] or backends[value.operationId]
        verbObj.backendUrl = backend.backendUrl
        verbObj.backendMethod = (backend.backendMethod == 'keep') and verb or backend.backendMethod
      else
        verbObj.backendUrl = ''
        verbObj.backendMethod = verb
      end
      verbObj.policies = policies
      verbObj.security = security
    end
  end
  return decoded
end

--- Parse backendUrl and backendMethod
-- @param swagger swagger file to parse
function parseBackends(swagger)
  local configObj = swagger["x-gateway-configuration"]
  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
  if configObj ~= nil then
    for _, obj in pairs(configObj.assembly.execute) do
      for policy, v in pairs(obj) do
        local res = {}
        if policy == "operation-switch" then
          local caseObj = v.case
          for _, case in pairs(caseObj) do
            for _, op in pairs(case.operations) do
              res[op] = {
                backendUrl = case.execute[1]["invoke"]["target-url"],
                backendMethod = case.execute[1]["invoke"].verb
              }
            end
          end
          return res
        end
        if policy == "invoke" then
          res["all"] = {
            backendUrl = v["target-url"],
            backendMethod = v.verb
          }
          return res
        end
      end
    end
  end
end

--- Parse policies in swagger
-- @param swagger swagger file to parse
function parsePolicies(swagger)
  local policies = {}
  -- parse rate limit
  policies = parseRateLimit(swagger, policies)
  policies = parseRequestMapping(swagger, policies)
  return policies
end

--- Parse rate limit
function parseRateLimit(swagger, policies)
  local rlObj = swagger["x-gateway-rate-limit"]
  rlObj = (rlObj == nil) and swagger["x-ibm-rate-limit"] or rlObj
  local unit
  if rlObj ~= nil then
    rlObj = rlObj[1]
    if rlObj.unit == "second" then
      unit = 1
    elseif rlObj.unit == "minute" then
      unit = 60
    elseif rlObj.unit == "hour" then
      unit = 3600
    elseif rlObj.unit == "day" then
      unit = 86400
    else
      unit = 60   -- default to minute
    end
    policies[#policies+1] = {
      type = "rateLimit",
      value = {
        interval = unit * rlObj.units,
        rate = rlObj.rate,
        scope = "api",
        subscription = true
      }
    }
  end
  return policies
end

--- Parse request mapping
function parseRequestMapping(swagger, policies)
  local valueList = {}
  if swagger["x-ibm-configuration"] ~= nil then
    for _, obj in pairs(swagger["x-ibm-configuration"].assembly.execute) do
      for policy, v in pairs(obj) do
        if policy == "set-variable" then
          for _, actionObj in pairs(v.actions) do
            local fromValue = actionObj.value
            local toParsedArray = {string.match(actionObj.set, "([^.]+).([^.]+).([^.]+)") }
            local toName = toParsedArray[3]
            local toLocation = toParsedArray[2]
            toLocation = toLocation == "headers" and "header" or toLocation
            valueList[#valueList+1] = {
              action = "insert",
              from = {
                value = fromValue
              },
              to = {
                name = toName,
                location = toLocation
              }
            }
          end
        end
      end
    end
  end
  if next(valueList) ~= nil then
    policies[#policies+1] ={
      type = "reqMapping",
      value = valueList
    }
  end
  return policies
end

--- Parse security in swagger
-- @param swagger swagger file to parse
function parseSecurity(swagger)
  local security = {}
  if swagger["securityDefinitions"] ~= nil then
    local secObject = swagger["securityDefinitions"]
    for key, sec in pairs(secObject) do
      if sec.type == 'apiKey' then
        security[#security+1] = {
          type = sec.type,
          scope = "api",
          header = sec.name
        }
      elseif sec.type == 'oauth2' then
        security[#security+1] = {
          type = sec.type,
          scope = "api",
          provider = key
        }
      end
    end
  end
  return security
end

function parseCors(swagger)
  local cors = { origin = nil, methods = nil }
  local configObj = swagger["x-gateway-configuration"]
  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
  if configObj.cors ~= nil then
    if configObj.cors.enabled == true then
      cors.origin = "true"
    elseif configObj.cors.enabled == false then
      cors.origin = "false"
    end
    return cors
  end
  return nil
end

return _M
