/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed 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.onosproject.segmentrouting.config;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.segmentrouting.config.NetworkConfig.LinkConfig;
import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * NetworkConfigManager manages all network configuration for switches, links
 * and any other state that needs to be configured for correct network
 * operation.
 *
 */
public class NetworkConfigManager implements NetworkConfigService {
    protected static final Logger log = LoggerFactory
            .getLogger(NetworkConfigManager.class);
    private static final String CONFIG_DIR = "../config";
    private static final String DEFAULT_CONFIG_FILE = "segmentrouting.conf";
    private final String configFileName = DEFAULT_CONFIG_FILE;
    /**
     * JSON Config file needs to use one of the following types for defining the
     * kind of switch or link it wishes to configure.
     */
    public static final String SEGMENT_ROUTER = "Router_SR";

    public static final String PKT_LINK = "pktLink";

    NetworkConfig networkConfig;
    private ConcurrentMap<DeviceId, SwitchConfig> configuredSwitches;
    private ConcurrentMap<Link, LinkConfig> configuredLinks;
    private Map<String, DeviceId> nameToDpid;

    @Override
    public SwitchConfigStatus checkSwitchConfig(DeviceId dpid) {
        SwitchConfig swc = configuredSwitches.get(dpid);
        if (networkConfig.getRestrictSwitches()) {
            // default deny behavior
            if (swc == null) {
                // switch is not configured - we deny this switch
                return new SwitchConfigStatus(NetworkConfigState.DENY, null,
                        "Switch not configured, in network denying switches by default.");
            }
            if (swc.isAllowed()) {
                // switch is allowed in config, return configured attributes
                return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc);
            } else {
                // switch has been configured off (administratively down)
                return new SwitchConfigStatus(NetworkConfigState.DENY, null,
                        "Switch configured down (allowed=false).");
            }
        } else {
            // default allow behavior
            if (swc == null) {
                // no config to add
                return new SwitchConfigStatus(NetworkConfigState.ACCEPT, null);
            }
            if (swc.isAllowed()) {
                // switch is allowed in config, return configured attributes
                return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc);
            } else {
                // switch has been configured off (administratively down)
                return new SwitchConfigStatus(NetworkConfigState.DENY, null,
                        "Switch configured down (allowed=false).");
            }
        }

    }

    @Override
    public LinkConfigStatus checkLinkConfig(Link linkTuple) {
        LinkConfig lkc = getConfiguredLink(linkTuple);
        // links are always disallowed if any one of the nodes that make up the
        // link are disallowed
        DeviceId linkNode1 = linkTuple.src().deviceId();
        SwitchConfigStatus scs1 = checkSwitchConfig(linkNode1);
        if (scs1.getConfigState() == NetworkConfigState.DENY) {
            return new LinkConfigStatus(NetworkConfigState.DENY, null,
                    "Link-node: " + linkNode1 + " denied by config: " + scs1.getMsg());
        }
        DeviceId linkNode2 = linkTuple.dst().deviceId();
        SwitchConfigStatus scs2 = checkSwitchConfig(linkNode2);
        if (scs2.getConfigState() == NetworkConfigState.DENY) {
            return new LinkConfigStatus(NetworkConfigState.DENY, null,
                    "Link-node: " + linkNode2 + " denied by config: " + scs2.getMsg());
        }
        if (networkConfig.getRestrictLinks()) {
            // default deny behavior
            if (lkc == null) {
                // link is not configured - we deny this link
                return new LinkConfigStatus(NetworkConfigState.DENY, null,
                        "Link not configured, in network denying links by default.");
            }
            if (lkc.isAllowed()) {
                // link is allowed in config, return configured attributes
                return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc);
            } else {
                // link has been configured off (administratively down)
                return new LinkConfigStatus(NetworkConfigState.DENY, null,
                        "Link configured down (allowed=false).");
            }
        } else {
            // default allow behavior
            if (lkc == null) {
                // no config to add
                return new LinkConfigStatus(NetworkConfigState.ACCEPT, null);
            }
            if (lkc.isAllowed()) {
                // link is allowed in config, return configured attributes
                return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc);
            } else {
                // link has been configured off (administratively down)
                return new LinkConfigStatus(NetworkConfigState.DENY, null,
                        "Link configured down (allowed=false).");
            }
        }

    }

    @Override
    public List<SwitchConfig> getConfiguredAllowedSwitches() {
        List<SwitchConfig> allowed = new ArrayList<SwitchConfig>();
        for (SwitchConfig swc : configuredSwitches.values()) {
            if (swc.isAllowed()) {
                allowed.add(swc);
            }
        }
        return allowed;
    }

    @Override
    public List<LinkConfig> getConfiguredAllowedLinks() {
        List<LinkConfig> allowed = new ArrayList<LinkConfig>();
        for (LinkConfig lkc : configuredLinks.values()) {
            if (lkc.isAllowed()) {
                allowed.add(lkc);
            }
        }
        return allowed;
    }

    @Override
    public DeviceId getDpidForName(String name) {
        if (nameToDpid.get(name) != null) {
            return nameToDpid.get(name);
        }
        return null;
    }

    // **************
    // Private methods
    // **************

    private void loadNetworkConfig() {
        File configFile = new File(CONFIG_DIR, configFileName);
        ObjectMapper mapper = new ObjectMapper();
        networkConfig = new NetworkConfig();

        try {
            networkConfig = mapper.readValue(configFile,
                                             NetworkConfig.class);
        } catch (JsonParseException e) {
            String err = String.format("JsonParseException while loading network "
                    + "config from file: %s: %s", configFileName,
                    e.getMessage());
            throw new NetworkConfigException.ErrorConfig(err);
        } catch (JsonMappingException e) {
            String err = String.format(
                    "JsonMappingException while loading network config "
                            + "from file: %s: %s",
                            configFileName,
                            e.getMessage());
            throw new NetworkConfigException.ErrorConfig(err);
        } catch (IOException e) {
            String err = String.format("IOException while loading network config "
                    + "from file: %s %s", configFileName, e.getMessage());
            throw new NetworkConfigException.ErrorConfig(err);
        }

        log.info("Network config specifies: {} switches and {} links",
                (networkConfig.getRestrictSwitches())
                        ? networkConfig.getSwitchConfig().size() : "default allow",
                        (networkConfig.getRestrictLinks())
                        ? networkConfig.getLinkConfig().size() : "default allow");
    }

    private void parseNetworkConfig() {
        List<SwitchConfig> swConfList = networkConfig.getSwitchConfig();
        List<LinkConfig> lkConfList = networkConfig.getLinkConfig();
        validateSwitchConfig(swConfList);
        createTypeSpecificSwitchConfig(swConfList);
        validateLinkConfig(lkConfList);
        createTypeSpecificLinkConfig(lkConfList);
        // TODO validate reachability matrix 'names' for configured dpids
    }

    private void createTypeSpecificSwitchConfig(List<SwitchConfig> swConfList) {
        for (SwitchConfig swc : swConfList) {
            nameToDpid.put(swc.getName(), swc.getDpid());
            String swtype = swc.getType();
            switch (swtype) {
            case SEGMENT_ROUTER:
                SwitchConfig sr = new SegmentRouterConfig(swc);
                configuredSwitches.put(sr.getDpid(), sr);
                break;
            default:
                throw new NetworkConfigException.UnknownSwitchType(swtype,
                        swc.getName());
            }
        }
    }

    private void createTypeSpecificLinkConfig(List<LinkConfig> lkConfList) {
        for (LinkConfig lkc : lkConfList) {
            String lktype = lkc.getType();
            switch (lktype) {
            case PKT_LINK:
                PktLinkConfig pk = new PktLinkConfig(lkc);
                for (Link lt : pk.getLinkTupleList()) {
                    configuredLinks.put(lt, pk);
                }
                break;
            default:
                throw new NetworkConfigException.UnknownLinkType(lktype,
                        lkc.getNodeDpid1(), lkc.getNodeDpid2());
            }
        }
    }

    private void validateSwitchConfig(List<SwitchConfig> swConfList) {
        Set<DeviceId> swDpids = new HashSet<DeviceId>();
        Set<String> swNames = new HashSet<String>();
        for (SwitchConfig swc : swConfList) {
            if (swc.getNodeDpid() == null || swc.getDpid() == null) {
                throw new NetworkConfigException.DpidNotSpecified(swc.getName());
            }
            // ensure both String and DeviceId values of dpid are set
            if (!swc.getDpid().equals(DeviceId.deviceId(swc.getNodeDpid()))) {
                throw new NetworkConfigException.SwitchDpidNotConverted(
                        swc.getName());
            }
            if (swc.getName() == null) {
                throw new NetworkConfigException.NameNotSpecified(swc.getDpid());
            }
            if (swc.getType() == null) {
                throw new NetworkConfigException.SwitchTypeNotSpecified(
                        swc.getDpid());
            }
            if (!swDpids.add(swc.getDpid())) {
                throw new NetworkConfigException.DuplicateDpid(swc.getDpid());
            }
            if (!swNames.add(swc.getName())) {
                throw new NetworkConfigException.DuplicateName(swc.getName());
            }
            // TODO Add more validations
        }
    }

    private void validateLinkConfig(List<LinkConfig> lkConfList) {
        for (LinkConfig lkc : lkConfList) {
            if (lkc.getNodeDpid1() == null || lkc.getNodeDpid2() == null) {
                throw new NetworkConfigException.LinkDpidNotSpecified(
                        lkc.getNodeDpid1(), lkc.getNodeDpid2());
            }
            // ensure both String and Long values are set
            if (!lkc.getDpid1().equals(DeviceId.deviceId(lkc.getNodeDpid1())) ||
                    !lkc.getDpid2().equals(DeviceId.deviceId(lkc.getNodeDpid2()))) {
                throw new NetworkConfigException.LinkDpidNotConverted(
                        lkc.getNodeDpid1(), lkc.getNodeDpid2());
            }
            if (lkc.getType() == null) {
                throw new NetworkConfigException.LinkTypeNotSpecified(
                        lkc.getNodeDpid1(), lkc.getNodeDpid2());
            }
            if (configuredSwitches.get(lkc.getDpid1()) == null) {
                throw new NetworkConfigException.LinkForUnknownSwitchConfig(
                        lkc.getNodeDpid1());
            }
            if (configuredSwitches.get(lkc.getDpid2()) == null) {
                throw new NetworkConfigException.LinkForUnknownSwitchConfig(
                        lkc.getNodeDpid2());
            }
            // TODO add more validations
        }

    }

    private LinkConfig getConfiguredLink(Link linkTuple) {
        LinkConfig lkc = null;
        // first try the unidirectional link with the ports assigned
        lkc = configuredLinks.get(linkTuple);
        return lkc;
    }


    /**
     * Initializes the network configuration manager module by
     * loading and parsing the network configuration file.
     */
    public void init() {
        loadNetworkConfig();
        configuredSwitches = new ConcurrentHashMap<DeviceId, SwitchConfig>();
        configuredLinks = new ConcurrentHashMap<Link, LinkConfig>();
        nameToDpid = new HashMap<String, DeviceId>();
        parseNetworkConfig();
    }
}
