/*
 * 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.isis.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.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 com.google.common.base.Preconditions.checkNotNull;
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)
    protected DeviceProviderRegistry deviceProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkProviderRegistry linkProviderRegistry;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected NetworkConfigService networkConfigService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkService linkService;
    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    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) {
        checkNotNull(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();

        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 = DefaultPortDescription.builder()
                    .withPortNumber(portNumber).isEnabled(true).build();
            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();
            }
        }
    }
}