/*
 * 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.
 */
package org.apache.dubbo.admin.service.impl;

import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.common.util.ConvertUtil;
import org.apache.dubbo.admin.common.util.RouteUtils;
import org.apache.dubbo.admin.common.util.YamlParser;
import org.apache.dubbo.admin.model.domain.Route;
import org.apache.dubbo.admin.model.dto.AccessDTO;
import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
import org.apache.dubbo.admin.model.dto.TagRouteDTO;
import org.apache.dubbo.admin.model.store.RoutingRule;
import org.apache.dubbo.admin.model.store.TagRoute;
import org.apache.dubbo.admin.service.RouteService;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * IbatisRouteService
 *
 */
@Component
public class RouteServiceImpl extends AbstractService implements RouteService {

    private String prefix = Constants.CONFIG_KEY;

    @Override
    public void createConditionRoute(ConditionRouteDTO conditionRoute) {
        String id = ConvertUtil.getIdFromDTO(conditionRoute);
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String existConfig = dynamicConfiguration.getConfig(path);
        RoutingRule existRule = null;
        if (existConfig != null) {
            existRule = YamlParser.loadObject(existConfig, RoutingRule.class);
        }
        existRule = RouteUtils.insertConditionRule(existRule, conditionRoute);
        //register2.7
        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(existRule));

        //register2.6
        if (StringUtils.isNotEmpty(conditionRoute.getService())) {
            Route old = convertRouteToOldRoute(conditionRoute);
            registry.register(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
        }

    }

    @Override
    public void updateConditionRoute(ConditionRouteDTO newConditionRoute) {
        String id = ConvertUtil.getIdFromDTO(newConditionRoute);
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String existConfig = dynamicConfiguration.getConfig(path);
        if (existConfig == null) {
            throw new ResourceNotFoundException("no existing condition route for path: " + path);
        }
        RoutingRule routingRule = YamlParser.loadObject(existConfig, RoutingRule.class);
        ConditionRouteDTO oldConditionRoute = RouteUtils.createConditionRouteFromRule(routingRule);
        routingRule = RouteUtils.insertConditionRule(routingRule, newConditionRoute);
        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(routingRule));

        //for 2.6
        if (StringUtils.isNotEmpty(newConditionRoute.getService())) {
            Route old = convertRouteToOldRoute(oldConditionRoute);
            Route updated = convertRouteToOldRoute(newConditionRoute);
            registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
            registry.register(updated.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
        }
    }

    @Override
    public void deleteConditionRoute(String id) {
        if (StringUtils.isEmpty(id)) {
            // throw exception
        }
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config == null) {
            //throw exception
        }
        RoutingRule route = YamlParser.loadObject(config, RoutingRule.class);
        List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(route.getConditions());
        if (blackWhiteList.size() != 0) {
           route.setConditions(blackWhiteList);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(route));
        } else {
            dynamicConfiguration.deleteConfig(path);
        }

        //for 2.6
        if (route.getScope().equals(Constants.SERVICE)) {
            RoutingRule originRule = YamlParser.loadObject(config, RoutingRule.class);
            ConditionRouteDTO conditionRouteDTO = RouteUtils.createConditionRouteFromRule(originRule);
            Route old = convertRouteToOldRoute(conditionRouteDTO);
            registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
        }
    }

    @Override
    public void deleteAccess(String id) {
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
            List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
            List<String> conditions = RouteUtils.filterConditionRuleFromConditions(ruleDTO.getConditions());
            if (conditions.size() == 0) {
                dynamicConfiguration.deleteConfig(path);
            } else {
                ruleDTO.setConditions(conditions);
                dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
            }
            //2.6
            if (ruleDTO.getScope().equals(Constants.SERVICE) && blackWhiteList.size() > 0) {
                Route route = RouteUtils.convertBlackWhiteListtoRoute(blackWhiteList, Constants.SERVICE, id);
                registry.unregister(route.toUrl());
            }
        }
    }

    @Override
    public void createAccess(AccessDTO accessDTO) {
        String id = ConvertUtil.getIdFromDTO(accessDTO);
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        List<String> blackWhiteList = RouteUtils.convertToBlackWhiteList(accessDTO);
        RoutingRule ruleDTO;
        if (config == null) {
            ruleDTO = new RoutingRule();
            ruleDTO.setEnabled(true);
            if (StringUtils.isNoneEmpty(accessDTO.getApplication())) {
                ruleDTO.setScope(Constants.APPLICATION);
            } else {
                ruleDTO.setScope(Constants.SERVICE);
            }
            ruleDTO.setKey(id);
            ruleDTO.setConditions(blackWhiteList);
        } else {
            ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
            if (ruleDTO.getConditions() == null) {
                ruleDTO.setConditions(blackWhiteList);
            } else {
                ruleDTO.getConditions().addAll(blackWhiteList);
            }
        }
        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));

        //for 2.6
        if (ruleDTO.getScope().equals("service")) {
            Route route = RouteUtils.convertAccessDTOtoRoute(accessDTO);
            registry.register(route.toUrl());
        }

    }

    @Override
    public AccessDTO findAccess(String id) {
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
            List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
            return RouteUtils.convertToAccessDTO(blackWhiteList, ruleDTO.getScope(), ruleDTO.getKey());
        }
        return null;
    }

    @Override
    public void updateAccess(AccessDTO accessDTO) {
        String key = ConvertUtil.getIdFromDTO(accessDTO);
        String path = getPath(key, Constants.CONDITION_ROUTE);
        List<String> blackWhiteList = RouteUtils.convertToBlackWhiteList(accessDTO);
        String config = dynamicConfiguration.getConfig(path);
        List<String> oldList = null;
        if (config != null) {
            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
            oldList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
            List<String> conditions = RouteUtils.filterConditionRuleFromConditions(ruleDTO.getConditions());
            conditions.addAll(blackWhiteList);
            ruleDTO.setConditions(conditions);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
        }

        //2.6
        if (StringUtils.isNotEmpty(accessDTO.getService())) {
            Route oldRoute = RouteUtils.convertBlackWhiteListtoRoute(oldList, Constants.SERVICE, key);
            Route newRoute = RouteUtils.convertAccessDTOtoRoute(accessDTO);
            registry.unregister(oldRoute.toUrl());
            registry.register(newRoute.toUrl());
        }
    }

    @Override
    public void enableConditionRoute(String id) {
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);

            if (ruleDTO.getScope().equals(Constants.SERVICE)) {
                //for2.6
                URL oldURL = convertRouteToOldRoute(RouteUtils.createConditionRouteFromRule(ruleDTO)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true);
                registry.unregister(oldURL);
                oldURL = oldURL.addParameter("enabled", true);
                registry.register(oldURL);
            }

            //2.7
            ruleDTO.setEnabled(true);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
        }

    }

    @Override
    public void disableConditionRoute(String serviceName) {
        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            RoutingRule routeRule = YamlParser.loadObject(config, RoutingRule.class);

            if (routeRule.getScope().equals(Constants.SERVICE)) {
                //for 2.6
                URL oldURL = convertRouteToOldRoute(RouteUtils.createConditionRouteFromRule(routeRule)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG,true);
                registry.unregister(oldURL);
                oldURL = oldURL.addParameter("enabled", false);
                registry.register(oldURL);
            }

            //2.7
            routeRule.setEnabled(false);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(routeRule));
        }

    }

    @Override
    public ConditionRouteDTO findConditionRoute(String id) {
        String path = getPath(id, Constants.CONDITION_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            RoutingRule routingRule = YamlParser.loadObject(config, RoutingRule.class);
            ConditionRouteDTO conditionRouteDTO = RouteUtils.createConditionRouteFromRule(routingRule);
            return conditionRouteDTO;
        }
        return null;
    }

    @Override
    public void createTagRoute(TagRouteDTO tagRoute) {
        String id = ConvertUtil.getIdFromDTO(tagRoute);
        String path = getPath(id,Constants.TAG_ROUTE);
        TagRoute store = RouteUtils.convertTagroutetoStore(tagRoute);
        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));
    }

    @Override
    public void updateTagRoute(TagRouteDTO tagRoute) {
        String id = ConvertUtil.getIdFromDTO(tagRoute);
        String path = getPath(id, Constants.TAG_ROUTE);
        if (dynamicConfiguration.getConfig(path) == null) {
            throw new ResourceNotFoundException("can not find tagroute: " + id);
            //throw exception
        }
        TagRoute store = RouteUtils.convertTagroutetoStore(tagRoute);
        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));

    }

    @Override
    public void deleteTagRoute(String id) {
        String path = getPath(id, Constants.TAG_ROUTE);
        dynamicConfiguration.deleteConfig(path);
    }

    @Override
    public void enableTagRoute(String id) {
        String path = getPath(id, Constants.TAG_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
            tagRoute.setEnabled(true);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(tagRoute));
        }

    }

    @Override
    public void disableTagRoute(String id) {
        String path = getPath(id, Constants.TAG_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
            tagRoute.setEnabled(false);
            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(tagRoute));
        }

    }

    @Override
    public TagRouteDTO findTagRoute(String id) {
        String path = getPath(id, Constants.TAG_ROUTE);
        String config = dynamicConfiguration.getConfig(path);
        if (config != null) {
            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
            return RouteUtils.convertTagroutetoDisplay(tagRoute);
        }
        return null;
    }

    private String getPath(String key, String type) {
        if (type.equals(Constants.CONDITION_ROUTE)) {
            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "condition-route";
        } else {
            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "tag-route";
        }
    }

    private String parseCondition(List<String> conditions) {
        StringBuilder when = new StringBuilder();
        StringBuilder then = new StringBuilder();
        for (String condition : conditions) {
            condition = condition.trim();
            if (condition.contains("=>")) {
                String[] array = condition.split("=>", 2);
                String consumer = array[0].trim();
                String provider = array[1].trim();
                if (consumer.length() != 0) {
                    if (when.length() != 0) {
                        when.append(" & ").append(consumer);
                    } else {
                        when.append(consumer);
                    }
                }
                if (provider.length() != 0) {
                    if (then.length() != 0) {
                        then.append(" & ").append(provider);
                    } else {
                        then.append(provider);
                    }
                }
            }
        }
        return (when.append(" => ").append(then)).toString();
    }

    private Route convertRouteToOldRoute(ConditionRouteDTO route) {
        Route old = new Route();
        old.setService(route.getService());
        old.setEnabled(route.isEnabled());
        old.setForce(route.isForce());
        old.setRuntime(route.isRuntime());
        old.setPriority(route.getPriority());
        String rule = parseCondition(route.getConditions());
        old.setRule(rule);
        return old;
    }
}
