/*
 * 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.provider.isis.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.onlab.util.Bandwidth;
import org.onosproject.isis.controller.IsisController;
import org.onosproject.isis.controller.topology.IsisLink;
import org.onosproject.isis.controller.topology.IsisLinkListener;
import org.onosproject.isis.controller.topology.IsisLinkTed;
import org.onosproject.isis.controller.topology.IsisRouter;
import org.onosproject.isis.controller.topology.IsisRouterId;
import org.onosproject.isis.controller.topology.IsisRouterListener;
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.config.NetworkConfigService;
import org.onosproject.net.config.basics.BandwidthCapacity;
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.slf4j.Logger;

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

import static org.slf4j.LoggerFactory.getLogger;

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

    public static final long PSEUDO_PORT = 0xffffffff;
    public static final String ADMINISTRATIVEGROUP = "administrativeGroup";
    public static final String TE_METRIC = "teMetric";
    public static final String MAXRESERVABLEBANDWIDTH = "maxReservableBandwidth";
    public static final String ROUTERID = "routerId";
    public static final String NEIGHBORID = "neighborId";
    private static final Logger log = getLogger(IsisTopologyProvider.class);
    // Default values for tunable parameters
    private static final String UNKNOWN = "unknown";
    final InternalTopologyProvider listener = new InternalTopologyProvider();
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceProviderRegistry deviceProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry linkProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService networkConfigService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkService linkService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IsisController 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;
    private HashMap<DeviceId, List<PortDescription>> portMap = new HashMap<>();

    /**
     * Creates an ISIS device provider.
     */
    public IsisTopologyProvider() {
        super(new ProviderId("l3", "org.onosproject.provider.isis"));
    }

    @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);
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        log.debug("IsisDeviceProvider::triggerProbe...!!!!");
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
        log.debug("IsisDeviceProvider::roleChanged...!!!!");
    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        log.debug("IsisDeviceProvider::isReachable...!!!!");
        return true;
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber, boolean enable) {
        log.debug("IsisDeviceProvider::changePortState...!!!!");
    }

    /**
     * Builds link description.
     *
     * @param isisLink ISIS link instance
     * @return link description
     */
    private LinkDescription buildLinkDes(IsisLink isisLink) {
        long srcAddress = 0;
        long dstAddress = 0;
        boolean localPseduo = false;
        boolean remotePseduo = false;
        String localSystemId = isisLink.localSystemId();
        String remoteSystemId = isisLink.remoteSystemId();
        //Changing of port numbers
        if (isisLink.interfaceIp() != null) {
            //srcAddress = isisLink.interfaceIp().toInt();
            srcAddress = (long) Long.parseUnsignedLong(Integer.toBinaryString(isisLink.interfaceIp().toInt()), 2);
        }
        if (isisLink.neighborIp() != null) {
            //dstAddress = isisLink.neighborIp().toInt();
            dstAddress = (long) Long.parseUnsignedLong(Integer.toBinaryString(isisLink.neighborIp().toInt()), 2);
        }
        DeviceId srcId = DeviceId.deviceId(IsisRouterId.uri(localSystemId));
        DeviceId dstId = DeviceId.deviceId(IsisRouterId.uri(remoteSystemId));
        if (checkIsDis(isisLink.localSystemId())) {
            localPseduo = true;
        } else if (checkIsDis(isisLink.remoteSystemId())) {
            remotePseduo = true;
        } else {
            log.debug("IsisDeviceProvider::buildLinkDes : unknown type.!");
        }

        if (localPseduo && srcAddress == 0) {
            srcAddress = PSEUDO_PORT;
        } else if (remotePseduo && dstAddress == 0) {
            dstAddress = PSEUDO_PORT;
        }

        ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
        ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));
        DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
        if (isisLink != null) {
            annotationBuilder = buildAnnotations(annotationBuilder, isisLink);
        }

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

    /**
     * Return the DIS value from the systemId.
     *
     * @param systemId system Id.
     * @return return true if DIS else false
     */
    public static boolean checkIsDis(String systemId) {
        StringTokenizer stringTokenizer = new StringTokenizer(systemId, "." + "-");
        int count = 0;
        while (stringTokenizer.hasMoreTokens()) {
            String str = stringTokenizer.nextToken();
            if (count == 3) {
                int x = Integer.parseInt(str);
                if (x > 0) {
                    return true;
                }
            }
            count++;
        }
        return false;
    }

    /**
     * Builds port description.
     *
     * @param deviceId   device ID for the port
     * @param portNumber port number of the link
     * @return list of port description
     */
    private List<PortDescription> buildPortDescriptions(DeviceId deviceId,
                                                        PortNumber portNumber) {
        List<PortDescription> portList;
        if (portMap.containsKey(deviceId)) {
            portList = portMap.get(deviceId);
        } else {
            portList = new ArrayList<>();
        }
        if (portNumber != null) {
            PortDescription portDescriptions = new DefaultPortDescription(portNumber, true);
            portList.add(portDescriptions);
        }
        portMap.put(deviceId, portList);

        return portList;
    }

    /**
     * Builds the annotation details.
     *
     * @param annotationBuilder default annotation builder instance
     * @param isisLink          ISIS link instance
     * @return annotation builder instance
     */
    private DefaultAnnotations.Builder buildAnnotations(DefaultAnnotations.Builder annotationBuilder,
                                                        IsisLink isisLink) {
        int administrativeGroup = 0;
        long teMetric = 0;
        Bandwidth maxReservableBandwidth = Bandwidth.bps(0);
        String routerId = null;
        String neighborId = null;

        //TE Info
        IsisLinkTed isisLinkTed = isisLink.linkTed();
        log.info("Ted Information:  {}", isisLinkTed.toString());
        administrativeGroup = isisLinkTed.administrativeGroup();
        teMetric = isisLinkTed.teDefaultMetric();
        maxReservableBandwidth = isisLinkTed.maximumReservableLinkBandwidth();
        routerId = isisLink.localSystemId();
        neighborId = isisLink.remoteSystemId();
        annotationBuilder.set(ADMINISTRATIVEGROUP, String.valueOf(administrativeGroup));
        annotationBuilder.set(TE_METRIC, String.valueOf(teMetric));
        annotationBuilder.set(MAXRESERVABLEBANDWIDTH, String.valueOf(maxReservableBandwidth));
        annotationBuilder.set(ROUTERID, String.valueOf(routerId));
        annotationBuilder.set(NEIGHBORID, String.valueOf(neighborId));
        return annotationBuilder;
    }

    /**
     * Internal device provider implementation.
     */
    private class InternalTopologyProvider implements IsisRouterListener, IsisLinkListener {

        @Override
        public void routerAdded(IsisRouter isisRouter) {
            String systemId = isisRouter.systemId();
            log.info("Added device {}", systemId);
            DeviceId deviceId = DeviceId.deviceId(IsisRouterId.uri(systemId));
            Device.Type deviceType = Device.Type.ROUTER;
            //If our routerType is Dr or Bdr type is PSEUDO
            if (isisRouter.isDis()) {
                deviceType = Device.Type.ROUTER;
            } else {
                deviceType = Device.Type.VIRTUAL;
            }
            ChassisId cId = new ChassisId();
            DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
            newBuilder.set(AnnotationKeys.TYPE, "L3");
            newBuilder.set("RouterId", systemId);
            DeviceDescription description =
                    new DefaultDeviceDescription(IsisRouterId.uri(systemId), deviceType, UNKNOWN, UNKNOWN, UNKNOWN,
                                                 UNKNOWN, cId, newBuilder.build());
            deviceProviderService.deviceConnected(deviceId, description);
            System.out.println("Device added: " + systemId);
        }

        @Override
        public void routerRemoved(IsisRouter isisRouter) {
            String systemId = isisRouter.systemId();
            log.info("Delete device {}", systemId);
            DeviceId deviceId = DeviceId.deviceId(IsisRouterId.uri(systemId));
            if (deviceProviderService == null) {
                return;
            }
            deviceProviderService.deviceDisconnected(deviceId);
            log.info("delete device {}", systemId);
        }

        @Override
        public void addLink(IsisLink isisLink) {
            log.debug("Addlink {}", isisLink.localSystemId());

            LinkDescription linkDes = buildLinkDes(isisLink);
            //Updating ports of the link
            //If already link exists, return
            if (linkService.getLink(linkDes.src(), linkDes.dst()) != null || linkProviderService == null) {
                return;
            }
            ConnectPoint destconnectPoint = linkDes.dst();
            PortNumber destport = destconnectPoint.port();
            if (destport.toLong() != 0) {
                deviceProviderService.updatePorts(linkDes.src().deviceId(),
                                                  buildPortDescriptions(linkDes.src().deviceId(),
                                                  linkDes.src().port()));
                deviceProviderService.updatePorts(linkDes.dst().deviceId(),
                                                  buildPortDescriptions(linkDes.dst().deviceId(),
                                                  linkDes.dst().port()));
                registerBandwidth(linkDes, isisLink);
                linkProviderService.linkDetected(linkDes);
                System.out.println("link desc " + linkDes.toString());
            }
        }

        @Override
        public void deleteLink(IsisLink isisLink) {
            log.debug("Delete link {}", isisLink.localSystemId());
            if (linkProviderService == null) {
                return;
            }
            LinkDescription linkDes = buildLinkDes(isisLink);
            linkProviderService.linkVanished(linkDes);
        }

        /**
         * Registers the bandwidth for source and destination points.
         *
         * @param linkDes  link description instance
         * @param isisLink ISIS link instance
         */
        private void registerBandwidth(LinkDescription linkDes, IsisLink isisLink) {
            if (isisLink == null) {
                log.error("Could not able to register bandwidth ");
                return;
            }
            IsisLinkTed isisLinkTed = isisLink.linkTed();
            Bandwidth maxReservableBw = isisLinkTed.maximumReservableLinkBandwidth();
            if (maxReservableBw != null) {
                if (maxReservableBw.compareTo(Bandwidth.bps(0)) == 0) {
                    return;
                }
                //Configure bandwidth for src and dst port
                BandwidthCapacity config = networkConfigService.addConfig(linkDes.src(), BandwidthCapacity.class);
                config.capacity(maxReservableBw).apply();

                config = networkConfigService.addConfig(linkDes.dst(), BandwidthCapacity.class);
                config.capacity(maxReservableBw).apply();
            }
        }
    }
}