--
-- 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.
--
local core           = require("apisix.core")
local plugin_checker = require("apisix.plugin").plugin_checker
local plugin         = require("apisix.plugin")

local pairs = pairs
local error = error


local plugin_configs


local _M = {
}


local function filter(global_rule)
    if not global_rule.value or not global_rule.value.plugins then
        return
    end
    plugin.set_plugins_meta_parent(global_rule.value.plugins, global_rule)
end


function _M.init_worker()
    local err
    plugin_configs, err = core.config.new("/plugin_configs", {
        automatic = true,
        item_schema = core.schema.plugin_config,
        checker = plugin_checker,
        filter = filter,
    })
    if not plugin_configs then
        error("failed to sync /plugin_configs: " .. err)
    end
end


function _M.plugin_configs()
    if not plugin_configs then
        return nil, nil
    end
    return plugin_configs.values, plugin_configs.conf_version
end


function _M.get(id)
    return plugin_configs:get(id)
end


function _M.merge(route_conf, plugin_config)
    if route_conf.prev_plugin_config_ver == plugin_config.modifiedIndex then
        return route_conf
    end

    if not route_conf.value.plugins then
        route_conf.value.plugins = {}
    end

    if route_conf.orig_plugins then
        -- recover
        route_conf.value.plugins = route_conf.orig_plugins
    else
        -- backup in the first time
        route_conf.orig_plugins = route_conf.value.plugins
    end

    route_conf.value.plugins = core.table.clone(route_conf.value.plugins)

    for name, value in pairs(plugin_config.value.plugins) do
        if not route_conf.value.plugins[name] then
            route_conf.value.plugins[name] = value
        end
    end

    route_conf.modifiedIndex = route_conf.orig_modifiedIndex .. "#" .. plugin_config.modifiedIndex
    route_conf.prev_plugin_config_ver = plugin_config.modifiedIndex

    return route_conf
end


return _M
