/*
 * Copyright 2016-present 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;

import com.google.common.collect.ImmutableSet;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.provider.ProviderId;
import org.opencord.cordconfig.CordConfigEvent;
import org.opencord.cordconfig.access.AccessAgentData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;

/**
 * Handles access agent config event which is required for CORD integration.
 */
public class CordConfigHandler {
    private static Logger log = LoggerFactory.getLogger(CordConfigHandler.class);
    private final SegmentRoutingManager srManager;

    /**
     * Constructs the CordConfigHandler.
     *
     * @param srManager Segment Routing manager
     */
    public CordConfigHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;
    }

    /**
     * Read initial access agent config for given device.
     *
     * @param deviceId ID of the device to be initialized
     */
    public void init(DeviceId deviceId) {
        // Try to read access agent config
        Optional<AccessAgentData> accessAgent =
                srManager.cordConfigService.getAccessAgent(deviceId);

        if (!accessAgent.isPresent()) {
            log.debug("No access agent config on {}. Skip.", deviceId);
            return;
        }

        processAccessAgentAdded(accessAgent.get());
    }

    // TODO javadoc
    protected void processAccessAgentAddedEvent(CordConfigEvent event) {
        log.debug("processAccessAgentAdded: {}, {}", event.subject(), event.prevSubject());
        processAccessAgentAdded((AccessAgentData) event.subject());
    }

    protected void processAccessAgentUpdatedEvent(CordConfigEvent event) {
        log.debug("processAccessAgentUpdated: {}, {}", event.subject(), event.prevSubject());
        processAccessAgentRemoved((AccessAgentData) event.prevSubject());
        processAccessAgentAdded((AccessAgentData) event.subject());
    }

    protected void processAccessAgentRemovedEvent(CordConfigEvent event) {
        log.debug("processAccessAgentRemoved: {}, {}", event.subject(), event.prevSubject());
        processAccessAgentRemoved((AccessAgentData) event.prevSubject());
    }

    protected void processAccessAgentAdded(AccessAgentData accessAgentData) {
        if (!srManager.mastershipService.isLocalMaster(accessAgentData.deviceId())) {
            log.debug("Not the master of {}. Abort.", accessAgentData.deviceId());
            return;
        }

        // Do not proceed if vtn location is missing
        if (!accessAgentData.getVtnLocation().isPresent()) {
            log.warn("accessAgentData does not contain vtn location. Abort.");
            return;
        }

        MacAddress agentMac = accessAgentData.getAgentMac();
        ConnectPoint agentLocation = accessAgentData.getVtnLocation().get();

        // Do not proceed if agent port doesn't have subnet configured
        Ip4Prefix agentSubnet = srManager.deviceConfiguration
                .getPortIPv4Subnet(agentLocation.deviceId(), agentLocation.port());
        if (agentSubnet == null) {
            log.warn("Agent port does not have subnet configuration. Abort.");
            return;
        }

        // Add host information for agent
        log.info("push host info for agent {}", agentMac);
        srManager.hostHandler.processHostAdded(createHost(agentMac, agentLocation));

        accessAgentData.getOltMacInfo().forEach((connectPoint, macAddress) -> {
            // Do not proceed if olt port has subnet configured
            Ip4Prefix oltSubnet = srManager.deviceConfiguration
                    .getPortIPv4Subnet(connectPoint.deviceId(), connectPoint.port());
            if (oltSubnet != null) {
                log.warn("OLT port has subnet configuration. Abort.");
                return;
            }

            // Add olt to the subnet of agent
            log.info("push subnet for olt {}", agentSubnet);
            srManager.deviceConfiguration.addSubnet(connectPoint, agentSubnet);
            srManager.routingRulePopulator.populateVlanMacFilters(connectPoint.deviceId());

            // Add host information for olt
            log.info("push host info for olt {}", macAddress);
            srManager.hostHandler.processHostAdded(createHost(macAddress, connectPoint));
        });
    }

    protected void processAccessAgentRemoved(AccessAgentData accessAgentData) {
        if (!srManager.mastershipService.isLocalMaster(accessAgentData.deviceId())) {
            log.debug("Not the master of {}. Abort.", accessAgentData.deviceId());
            return;
        }

        // Do not proceed if vtn location is missing
        if (!accessAgentData.getVtnLocation().isPresent()) {
            log.warn("accessAgentData does not contain vtn location. Abort.");
            return;
        }

        MacAddress agentMac = accessAgentData.getAgentMac();
        ConnectPoint agentLocation = accessAgentData.getVtnLocation().get();

        // Do not proceed if olt port doesn't have subnet configured
        Ip4Prefix agentSubnet = srManager.deviceConfiguration
                .getPortIPv4Subnet(agentLocation.deviceId(), agentLocation.port());
        if (agentSubnet == null) {
            log.warn("Agent port does not have subnet configuration. Abort.");
            return;
        }

        // Remove host information for agent
        log.info("delete host info for agent {}", agentMac);
        srManager.hostHandler.processHostRemoved(createHost(agentMac, agentLocation));

        accessAgentData.getOltMacInfo().forEach((connectPoint, macAddress) -> {
            // Do not proceed if agent port doesn't have subnet configured
            Ip4Prefix oltSubnet = srManager.deviceConfiguration
                    .getPortIPv4Subnet(connectPoint.deviceId(), connectPoint.port());
            if (oltSubnet == null) {
                log.warn("OLT port does not have subnet configuration. Abort.");
                return;
            }

            // Remove host information for olt
            log.info("delete host info for olt {}", macAddress);
            srManager.hostHandler.processHostRemoved(createHost(macAddress, connectPoint));

            // Remove olt to the subnet of agent
            log.info("delete subnet for olt {}", agentSubnet);
            srManager.deviceConfiguration.removeSubnet(connectPoint, agentSubnet);
            srManager.routingRulePopulator.populateVlanMacFilters(connectPoint.deviceId());
        });
    }

    private Host createHost(MacAddress macAddress, ConnectPoint location) {
        return new DefaultHost(
                new ProviderId("host", "org.onosproject.segmentrouting"),
                HostId.hostId(macAddress),
                macAddress,
                VlanId.NONE,
                new HostLocation(location, System.currentTimeMillis()),
                ImmutableSet.of());
    }
}
