/*
 * Copyright 2015-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.provider.pcep.topology.impl;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onosproject.cluster.ClusterService;
import org.onosproject.mastership.MastershipAdminService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link.Type;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.OchPort;
import org.onosproject.net.OduCltPort;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.OchPortDescription;
import org.onosproject.net.device.OduCltPortDescription;
import org.onosproject.net.device.OmsPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pcep.api.DeviceCapability;
import org.onosproject.pcep.api.PcepController;
import org.onosproject.pcep.api.PcepDpid;
import org.onosproject.pcep.api.PcepLink;
import org.onosproject.pcep.api.PcepLink.PortType;
import org.onosproject.pcep.api.PcepLinkListener;
import org.onosproject.pcep.api.PcepOperator.OperationType;
import org.onosproject.pcep.api.PcepSwitch;
import org.onosproject.pcep.api.PcepSwitchListener;
import org.onosproject.pcep.controller.PccId;
import org.onosproject.pcep.controller.PcepClient;
import org.onosproject.pcep.controller.PcepClientController;
import org.onosproject.pcep.controller.PcepNodeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.pcep.api.PcepDpid.uri;

/**
 * Provider which uses an PCEP controller to detect network infrastructure
 * topology.
 */
@Component(immediate = true)
public class PcepTopologyProvider extends AbstractProvider
        implements LinkProvider, DeviceProvider {

    /**
     * Creates instance of PCEP topology provider.
     */
    public PcepTopologyProvider() {
        super(new ProviderId("l3", "org.onosproject.provider.pcep"));
    }

    private static final Logger log = LoggerFactory
            .getLogger(PcepTopologyProvider.class);

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry linkProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceProviderRegistry deviceProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PcepController controller;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkService linkService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipAdminService mastershipAdminService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ClusterService clusterService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PcepClientController pcepClientController;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry netConfigRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService netConfigService;

    private DeviceProviderService deviceProviderService;
    private LinkProviderService linkProviderService;

    private HashMap<Long, List<PortDescription>> portMap = new HashMap<>();
    private InternalLinkProvider listener = new InternalLinkProvider();

    private final ConfigFactory<DeviceId, DeviceCapability> configFactory =
            new ConfigFactory<DeviceId, DeviceCapability>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
                    DeviceCapability.class, "deviceCapability", true) {
                @Override
                public DeviceCapability createConfig() {
                    return new DeviceCapability();
                }
            };

    @Activate
    public void activate() {
        linkProviderService = linkProviderRegistry.register(this);
        deviceProviderService = deviceProviderRegistry.register(this);
        controller.addListener(listener);
        controller.addLinkListener(listener);
        pcepClientController.addNodeListener(listener);
        netConfigRegistry.registerConfigFactory(configFactory);
    }

    @Deactivate
    public void deactivate() {
        linkProviderRegistry.unregister(this);
        linkProviderService = null;
        controller.removeListener(listener);
        controller.removeLinkListener(listener);
        pcepClientController.removeNodeListener(listener);
        netConfigRegistry.unregisterConfigFactory(configFactory);
    }

    private List<PortDescription> buildPortDescriptions(PcepDpid dpid,
                                                        Port port,
                                                        PortType portType) {

        List<PortDescription> portList;

        if (portMap.containsKey(dpid.value())) {
            portList = portMap.get(dpid.value());
        } else {
            portList = new ArrayList<>();
        }
        if (port != null && portType != null) {
            portList.add(buildPortDescription(port, portType));
        }

        portMap.put(dpid.value(), portList);
        return portList;
    }

    private PortDescription buildPortDescription(Port port, PortType portType) {
        PortDescription portDescription;

        switch (portType) {
            case OCH_PORT:
                OchPort ochp = (OchPort) port;
                portDescription = new OchPortDescription(ochp.number(), ochp.isEnabled(),
                        ochp.signalType(), ochp.isTunable(),
                        ochp.lambda());
                break;
            case ODU_PORT:
                OduCltPort odup = (OduCltPort) port;
                portDescription = new OduCltPortDescription(odup.number(), odup.isEnabled(),
                        odup.signalType());
                break;
            case OMS_PORT:
                OmsPort op = (OmsPort) port;
                portDescription = new OmsPortDescription(op.number(), op.isEnabled(), op.minFrequency(),
                        op.maxFrequency(), op.grid());
                break;
            default:
                portDescription = new DefaultPortDescription(port.number(), port.isEnabled());
                break;
        }
        return portDescription;
    }

    /**
     * Build a link description from a pcep link.
     *
     * @param pceLink pcep link
     * @return LinkDescription onos link description
     */
    private LinkDescription buildLinkDescription(PcepLink pceLink) {
        LinkDescription ld;
        checkNotNull(pceLink);
        DeviceId srcDeviceID = deviceId(uri(pceLink.linkSrcDeviceID()));
        DeviceId dstDeviceID = deviceId(uri(pceLink.linkDstDeviceId()));

        deviceProviderService
                .updatePorts(srcDeviceID,
                        buildPortDescriptions(pceLink.linkSrcDeviceID(),
                                pceLink.linkSrcPort(), pceLink.portType()));

        deviceProviderService
                .updatePorts(dstDeviceID,
                        buildPortDescriptions(pceLink.linkDstDeviceId(),
                                pceLink.linkDstPort(), pceLink.portType()));

        ConnectPoint src = new ConnectPoint(srcDeviceID, pceLink.linkSrcPort().number());

        ConnectPoint dst = new ConnectPoint(dstDeviceID, pceLink.linkDstPort().number());

        DefaultAnnotations extendedAttributes = DefaultAnnotations
                .builder()
                .set("subType", String.valueOf(pceLink.linkSubType()))
                .set("workState", pceLink.linkState())
                .set("distance", String.valueOf(pceLink.linkDistance()))
                .set("capType", pceLink.linkCapacityType().toLowerCase())
                .set("avail_" + pceLink.linkCapacityType().toLowerCase(),
                        String.valueOf(pceLink.linkAvailValue()))
                .set("max_" + pceLink.linkCapacityType().toLowerCase(),
                        String.valueOf(pceLink.linkMaxValue())).build();
        // construct the link
        ld = new DefaultLinkDescription(src, dst, Type.OPTICAL, extendedAttributes);
        return ld;
    }

    private class InternalLinkProvider
            implements PcepSwitchListener, PcepLinkListener, PcepNodeListener {

        @Override
        public void switchAdded(PcepDpid dpid) {
            if (deviceProviderService == null) {
                return;
            }
            DeviceId deviceId = deviceId(uri(dpid));
            PcepSwitch sw = controller.getSwitch(dpid);
            checkNotNull(sw, "device should not null.");
            // The default device type is switch.
            ChassisId cId = new ChassisId(dpid.value());
            Device.Type deviceType;

            switch (sw.getDeviceType()) {
                case ROADM:
                    deviceType = Device.Type.ROADM;
                    break;
                case OTN:
                    deviceType = Device.Type.SWITCH;
                    break;
                case ROUTER:
                    deviceType = Device.Type.ROUTER;
                    break;
                default:
                    deviceType = Device.Type.OTHER;
            }

            DeviceDescription description = new DefaultDeviceDescription(
                    deviceId.uri(),
                    deviceType,
                    sw.manufacturerDescription(),
                    sw.hardwareDescription(),
                    sw.softwareDescription(),
                    sw.serialNumber(),
                    cId);
            deviceProviderService.deviceConnected(deviceId, description);

        }

        @Override
        public void switchRemoved(PcepDpid dpid) {
            if (deviceProviderService == null || linkProviderService == null) {
                return;
            }
            deviceProviderService.deviceDisconnected(deviceId(uri(dpid)));

            linkProviderService.linksVanished(DeviceId.deviceId(uri(dpid)));
        }

        @Override
        public void switchChanged(PcepDpid dpid) {
            // TODO Auto-generated method stub

        }

        @Override
        public void handlePceplink(PcepLink link) {

            OperationType operType = link.getOperationType();
            LinkDescription ld = buildLinkDescription(link);
            if (ld == null) {
                log.error("Invalid link info.");
                return;
            }
            switch (operType) {
                case ADD:
                case UPDATE:
                    linkProviderService.linkDetected(ld);
                    break;

                case DELETE:
                    linkProviderService.linkVanished(ld);
                    break;

                default:
                    break;

            }
        }

        @Override
        public void addDevicePcepConfig(PcepClient pc) {
            if (netConfigRegistry == null) {
                log.error("Cannot add PCEP device capability as network config service is not available.");
                return;
            }
            DeviceId pccDeviceId = DeviceId.deviceId(String.valueOf(pc.getPccId().ipAddress()));
            DeviceCapability deviceCap = netConfigService.addConfig(pccDeviceId, DeviceCapability.class);
            deviceCap.setLabelStackCap(pc.capability().labelStackCapability())
                .setLocalLabelCap(pc.capability().pceccCapability())
                .setSrCap(pc.capability().srCapability())
                .apply();
        }

        @Override
        public void deleteDevicePcepConfig(PccId pccId) {
            if (netConfigRegistry == null) {
                log.error("Cannot remove PCEP device capability as network config service is not available.");
                return;
            }
            DeviceId pccDeviceId = DeviceId.deviceId(String.valueOf(pccId.ipAddress()));
            netConfigService.removeConfig(pccDeviceId, DeviceCapability.class);
        }
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        // TODO Auto-generated method stub
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                boolean enable) {
        // TODO Auto-generated method stub
    }
}
