/*
 * 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.newoptical;

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.onlab.util.Bandwidth;
import org.onosproject.newoptical.api.OpticalConnectivityId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;

import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkState;

/**
 * Entity to store optical connectivity request and related information.
 */
@Beta
public class OpticalConnectivity {

    private final OpticalConnectivityId id;
    private final List<Link> links;
    private final Bandwidth requestBandwidth;
    private final Duration requestLatency;

    /**
     * Set of packet link that is not yet established.
     * Packet links in this set are expected to be discovered after underlying (optical) path has been provisioned.
     */
    private final ImmutableSet<PacketLinkRealizedByOptical> unestablishedLinks;

    /**
     * Set of packet link that is already established.
     */
    private final ImmutableSet<PacketLinkRealizedByOptical> establishedLinks;

    public OpticalConnectivity(OpticalConnectivityId id,
                               List<Link> links,
                               Bandwidth requestBandwidth,
                               Duration requestLatency,
                               Set<PacketLinkRealizedByOptical> unestablishedLinks,
                               Set<PacketLinkRealizedByOptical> establishedLinks) {
        this.id = id;
        this.links = ImmutableList.copyOf(links);
        this.requestBandwidth = requestBandwidth;
        this.requestLatency = requestLatency;
        this.unestablishedLinks = ImmutableSet.copyOf(unestablishedLinks);
        this.establishedLinks = ImmutableSet.copyOf(establishedLinks);
    }

    private OpticalConnectivity(OpticalConnectivity connectivity) {
        this.id = connectivity.id;
        this.links = ImmutableList.copyOf(connectivity.links);
        this.requestBandwidth = connectivity.requestBandwidth;
        this.requestLatency = connectivity.requestLatency;
        this.unestablishedLinks = ImmutableSet.copyOf(connectivity.unestablishedLinks);
        this.establishedLinks = ImmutableSet.copyOf(connectivity.establishedLinks);
    }

    public boolean isAllRealizingLinkEstablished() {
        // Check if all links are established
        return unestablishedLinks.isEmpty();
    }

    public boolean isAllRealizingLinkNotEstablished() {
        // Check if any link is not established
        return establishedLinks.isEmpty();
    }

    public OpticalConnectivityId id() {
        return id;
    }

    public List<Link> links() {
        return links;
    }

    public Bandwidth bandwidth() {
        return requestBandwidth;
    }

    public Duration latency() {
        return requestLatency;
    }

    public Set<PacketLinkRealizedByOptical> getEstablishedLinks() {
        return establishedLinks;
    }

    public Set<PacketLinkRealizedByOptical> getUnestablishedLinks() {
        return unestablishedLinks;
    }

    public OpticalConnectivity setLinkEstablished(ConnectPoint src,
                                                  ConnectPoint dst,
                                                  boolean established) {
        Set<PacketLinkRealizedByOptical> newEstablishedLinks;
        Set<PacketLinkRealizedByOptical> newUnestablishedLinks;

        if (established) {
            // move PacketLink from unestablished set to established set
            Optional<PacketLinkRealizedByOptical> link = this.unestablishedLinks.stream()
                    .filter(l -> l.isBetween(src, dst)).findAny();
            checkState(link.isPresent());

            newUnestablishedLinks = this.unestablishedLinks.stream()
                    .filter(l -> !l.isBetween(src, dst))
                    .collect(Collectors.toSet());
            newEstablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder()
                    .addAll(this.establishedLinks)
                    .add(link.get())
                    .build();
        } else {
            // move PacketLink from established set to unestablished set
            Optional<PacketLinkRealizedByOptical> link = this.establishedLinks.stream()
                    .filter(l -> l.isBetween(src, dst)).findAny();
            checkState(link.isPresent());

            newEstablishedLinks = this.establishedLinks.stream()
                    .filter(l -> !l.isBetween(src, dst))
                    .collect(Collectors.toSet());
            newUnestablishedLinks = ImmutableSet.<PacketLinkRealizedByOptical>builder()
                    .addAll(this.unestablishedLinks)
                    .add(link.get())
                    .build();
        }

        return new OpticalConnectivity(this.id,
                this.links,
                this.requestBandwidth,
                this.requestLatency,
                newUnestablishedLinks,
                newEstablishedLinks);
    }

    public Set<PacketLinkRealizedByOptical> getRealizingLinks() {
        return ImmutableSet.<PacketLinkRealizedByOptical>builder()
                .addAll(unestablishedLinks)
                .addAll(establishedLinks)
                .build();
    }

    public static OpticalConnectivity copyOf(OpticalConnectivity connectivity) {
        return new OpticalConnectivity(connectivity);
    }
}
