/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.ospf.topology.impl;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onosproject.net.AnnotationKeys;
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;
import org.onosproject.net.MastershipRole;
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.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.ospf.controller.OspfController;
import org.onosproject.ospf.controller.OspfLinkTed;
import org.onosproject.ospf.controller.OspfRouter;
import org.onosproject.ospf.controller.OspfRouterId;
import org.onosproject.ospf.controller.OspfRouterListener;
import org.onosproject.ospf.controller.OspfLinkListener;
import org.slf4j.Logger;

import java.util.LinkedList;
import java.util.List;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider which advertises device descriptions to the core.
 */
@Component(immediate = true)
public class OspfTopologyProvider extends AbstractProvider implements DeviceProvider, LinkProvider {

    public static final long PSEUDO_PORT = 0xffffffff;
    private static final Logger log = getLogger(OspfTopologyProvider.class);
    // Default values for tunable parameters
    private static final String UNKNOWN = "unknown";
    final InternalTopologyProvider listener = new InternalTopologyProvider();
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceProviderRegistry deviceProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkProviderRegistry linkProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkService linkService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected OspfController controller;
    //This Interface that defines how this provider can interact with the core.
    private LinkProviderService linkProviderService;
    // The interface that defines how this Provider can interact with the core
    private DeviceProviderService deviceProviderService;

    /**
     * Creates an OSPF device provider.
     */
    public OspfTopologyProvider() {
        super(new ProviderId("l3", "org.onosproject.provider.ospf"));
    }

    @Activate
    public void activate() {
        deviceProviderService = deviceProviderRegistry.register(this);
        linkProviderService = linkProviderRegistry.register(this);
        controller.addRouterListener(listener);
        controller.addLinkListener(listener);
        log.debug("IsisDeviceProvider::activate...!!!!");
    }

    @Deactivate
    public void deactivate() {
        log.debug("IsisDeviceProvider::deactivate...!!!!");
        deviceProviderRegistry.unregister(this);
        deviceProviderService = null;
        linkProviderRegistry.unregister(this);
        linkProviderService = null;
        controller.removeRouterListener(listener);
        controller.removeLinkListener(listener);
        log.info("deactivated...!!!");
    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        return true;
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber, boolean enable) {
        log.info("changePortState on device {}", deviceId);
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        log.info("Triggering probe on device {}", deviceId);
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
        log.info("Accepting mastership role change for device {}", deviceId);
    }

    /**
     * Builds link description.
     *
     * @param ospfRouter  OSPF router instance
     * @param ospfLinkTed OSPF link TED instance
     * @return link description instance
     */
    private LinkDescription buildLinkDes(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
        long srcAddress = 0;
        long dstAddress = 0;
        boolean localPseduo = false;
        //Changing of port numbers
        srcAddress = Ip4Address.valueOf(ospfRouter.routerIp().toString()).toInt();
        dstAddress = Ip4Address.valueOf(ospfRouter.neighborRouterId().toString()).toInt();
        DeviceId srcId = DeviceId.deviceId(OspfRouterId.uri(ospfRouter.routerIp()));
        DeviceId dstId = DeviceId.deviceId(OspfRouterId.uri(ospfRouter.neighborRouterId()));
        if (ospfRouter.isDr()) {
            localPseduo = true;
        }
        if (localPseduo && srcAddress == 0) {
            srcAddress = PSEUDO_PORT;
        }

        ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
        ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));

        return new DefaultLinkDescription(src, dst, Link.Type.DIRECT, false);
    }

    /**
     * Internal topology Provider implementation.
     */
    protected class InternalTopologyProvider implements OspfRouterListener, OspfLinkListener {

        @Override
        public void routerAdded(OspfRouter ospfRouter) {
            String routerId = ospfRouter.routerIp().toString();
            log.info("Added device {}", routerId);
            DeviceId deviceId = DeviceId.deviceId(OspfRouterId.uri(ospfRouter.routerIp()));
            Device.Type deviceType = Device.Type.ROUTER;
            //If our routerType is Dr or Bdr type is PSEUDO
            if (ospfRouter.isDr()) {
                deviceType = Device.Type.ROUTER;
            } else {
                deviceType = Device.Type.VIRTUAL;
            }
            //deviceId = DeviceId.deviceId(routerDetails);
            ChassisId cId = new ChassisId();
            DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();

            newBuilder.set(AnnotationKeys.TYPE, "l3");
            newBuilder.set("routerId", routerId);
            DeviceDescription description =
                    new DefaultDeviceDescription(OspfRouterId.uri(ospfRouter.routerIp()),
                            deviceType, UNKNOWN, UNKNOWN, UNKNOWN,
                            UNKNOWN, cId, newBuilder.build());
            deviceProviderService.deviceConnected(deviceId, description);
        }

        @Override
        public void routerRemoved(OspfRouter ospfRouter) {
            String routerId = ospfRouter.routerIp().toString();
            log.info("Delete device {}", routerId);
            DeviceId deviceId = DeviceId.deviceId(OspfRouterId.uri(ospfRouter.routerIp()));
            if (deviceProviderService == null) {
                return;
            }
            deviceProviderService.deviceDisconnected(deviceId);
            log.info("delete device {}", routerId);
        }

        @Override
        public void addLink(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
            log.debug("Addlink {}", ospfRouter.routerIp());
            LinkDescription linkDes = buildLinkDes(ospfRouter, ospfLinkTed);
            //If already link exists, return
            if (linkService.getLink(linkDes.src(), linkDes.dst()) != null || linkProviderService == null) {
                return;
            }
            //Updating ports of the link
            List<PortDescription> srcPortDescriptions = new LinkedList<>();
            srcPortDescriptions.add(DefaultPortDescription.builder()
                    .withPortNumber(linkDes.src().port()).isEnabled(true).build());
            deviceProviderService.updatePorts(linkDes.src().deviceId(), srcPortDescriptions);

            List<PortDescription> dstPortDescriptions = new LinkedList<>();
            dstPortDescriptions.add(DefaultPortDescription.builder()
                    .withPortNumber(linkDes.dst().port()).isEnabled(true).build());
            deviceProviderService.updatePorts(linkDes.dst().deviceId(), dstPortDescriptions);
            linkProviderService.linkDetected(linkDes);
        }

        @Override
        public void deleteLink(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
            log.debug("Delete link {}", ospfRouter.routerIp().toString());
            if (linkProviderService == null) {
                return;
            }
            LinkDescription linkDes = buildLinkDes(ospfRouter, ospfLinkTed);
            //Updating ports of the link
            List<PortDescription> srcPortDescriptions = new LinkedList<>();
            srcPortDescriptions.add(DefaultPortDescription.builder()
                    .withPortNumber(linkDes.src().port()).isEnabled(true).build());
            deviceProviderService.updatePorts(linkDes.src().deviceId(), srcPortDescriptions);

            List<PortDescription> dstPortDescriptions = new LinkedList<>();
            dstPortDescriptions.add(DefaultPortDescription.builder()
                    .withPortNumber(linkDes.dst().port()).isEnabled(true).build());
            deviceProviderService.updatePorts(linkDes.dst().deviceId(), dstPortDescriptions);
            linkProviderService.linkVanished(linkDes);
        }

        @Override
        public void routerChanged(OspfRouter ospfRouter) {
            log.info("Router changed is not supported currently");
        }
    }
}
