/*
 * Copyright 2014-2015 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.store.trivial.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.Service;
import org.onlab.util.PositionalParameterStringFormatter;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Annotations;
import org.onosproject.net.Link;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.resource.Bandwidth;
import org.onosproject.net.resource.BandwidthResourceAllocation;
import org.onosproject.net.resource.LambdaResource;
import org.onosproject.net.resource.LambdaResourceAllocation;
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceEvent;
import org.onosproject.net.resource.LinkResourceStore;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceAllocationException;
import org.onosproject.net.resource.ResourceType;
import org.slf4j.Logger;

import com.google.common.collect.ImmutableList;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Manages link resources using trivial in-memory structures implementation.
 */
@Component(immediate = true)
@Service
public class SimpleLinkResourceStore implements LinkResourceStore {
    private static final Bandwidth DEFAULT_BANDWIDTH = Bandwidth.mbps(1_000);
    private final Logger log = getLogger(getClass());

    private Map<IntentId, LinkResourceAllocations> linkResourceAllocationsMap;
    private Map<Link, Set<LinkResourceAllocations>> allocatedResources;
    private Map<Link, Set<ResourceAllocation>> freeResources;

    @Activate
    public void activate() {
        linkResourceAllocationsMap = new HashMap<>();
        allocatedResources = new HashMap<>();
        freeResources = new HashMap<>();

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        log.info("Stopped");
    }

    /**
     * Returns free resources for a given link obtaining from topology
     * information.
     *
     * @param link the target link
     * @return free resources
     */
    private synchronized Set<ResourceAllocation> readOriginalFreeResources(Link link) {
        Annotations annotations = link.annotations();
        Set<ResourceAllocation> allocations = new HashSet<>();

        try {
            int waves = Integer.parseInt(annotations.value(AnnotationKeys.OPTICAL_WAVES));
            for (int i = 1; i <= waves; i++) {
                allocations.add(new LambdaResourceAllocation(LambdaResource.valueOf(i)));
            }
        } catch (NumberFormatException e) {
            log.debug("No optical.wave annotation on link %s", link);
        }

        Bandwidth bandwidth = DEFAULT_BANDWIDTH;
        try {
            bandwidth = Bandwidth.mbps((Double.parseDouble(annotations.value(AnnotationKeys.BANDWIDTH))));
        } catch (NumberFormatException e) {
            log.debug("No bandwidth annotation on link %s", link);
        }
        allocations.add(
                new BandwidthResourceAllocation(bandwidth));
        return allocations;
    }

    /**
     * Finds and returns {@link BandwidthResourceAllocation} object from a given
     * set.
     *
     * @param freeRes a set of ResourceAllocation object.
     * @return {@link BandwidthResourceAllocation} object if found, otherwise
     *         {@link BandwidthResourceAllocation} object with 0 bandwidth
     *
     */
    private synchronized BandwidthResourceAllocation getBandwidth(
            Set<ResourceAllocation> freeRes) {
        for (ResourceAllocation res : freeRes) {
            if (res.type() == ResourceType.BANDWIDTH) {
                return (BandwidthResourceAllocation) res;
            }
        }
        return new BandwidthResourceAllocation(Bandwidth.bps(0));
    }

    /**
     * Subtracts given resources from free resources for given link.
     *
     * @param link the target link
     * @param allocations the resources to be subtracted
     */
    private synchronized void subtractFreeResources(Link link,
            LinkResourceAllocations allocations) {
        // TODO Use lock or version for updating freeResources.
        checkNotNull(link);
        Set<ResourceAllocation> freeRes = new HashSet<>(getFreeResources(link));
        Set<ResourceAllocation> subRes = allocations.getResourceAllocation(link);
        for (ResourceAllocation res : subRes) {
            switch (res.type()) {
            case BANDWIDTH:
                BandwidthResourceAllocation ba = getBandwidth(freeRes);
                double requestedBandwidth =
                        ((BandwidthResourceAllocation) res).bandwidth().toDouble();
                double newBandwidth = ba.bandwidth().toDouble() - requestedBandwidth;
                if (newBandwidth < 0.0) {
                    throw new ResourceAllocationException(
                            PositionalParameterStringFormatter.format(
                            "Unable to allocate bandwidth for link {} "
                            + "requested amount is {} current allocation is {}",
                                    link,
                                    requestedBandwidth,
                                    ba));
                }
                freeRes.remove(ba);
                freeRes.add(new BandwidthResourceAllocation(
                        Bandwidth.bps(newBandwidth)));
                break;
            case LAMBDA:
                final boolean lambdaAvailable = freeRes.remove(res);
                if (!lambdaAvailable) {
                    int requestedLambda =
                            ((LambdaResourceAllocation) res).lambda().toInt();
                    throw new ResourceAllocationException(
                            PositionalParameterStringFormatter.format(
                                    "Unable to allocate lambda for link {} lambda is {}",
                                    link,
                                    requestedLambda));
                }
                break;
            default:
                break;
            }
        }
        freeResources.put(link, freeRes);

    }

    /**
     * Adds given resources to free resources for given link.
     *
     * @param link the target link
     * @param allocations the resources to be added
     */
    private synchronized void addFreeResources(Link link,
            LinkResourceAllocations allocations) {
        // TODO Use lock or version for updating freeResources.
        Set<ResourceAllocation> freeRes = new HashSet<>(getFreeResources(link));
        Set<ResourceAllocation> addRes = allocations.getResourceAllocation(link);
        for (ResourceAllocation res : addRes) {
            switch (res.type()) {
            case BANDWIDTH:
                BandwidthResourceAllocation ba = getBandwidth(freeRes);
                double requestedBandwidth =
                        ((BandwidthResourceAllocation) res).bandwidth().toDouble();
                double newBandwidth = ba.bandwidth().toDouble() + requestedBandwidth;
                freeRes.remove(ba);
                freeRes.add(new BandwidthResourceAllocation(
                        Bandwidth.bps(newBandwidth)));
                break;
            case LAMBDA:
                checkState(freeRes.add(res));
                break;
            default:
                break;
            }
        }
        freeResources.put(link, freeRes);
    }

    @Override
    public synchronized Set<ResourceAllocation> getFreeResources(Link link) {
        checkNotNull(link);
        Set<ResourceAllocation> freeRes = freeResources.get(link);
        if (freeRes == null) {
            freeRes = readOriginalFreeResources(link);
        }

        return freeRes;
    }

    @Override
    public synchronized void allocateResources(LinkResourceAllocations allocations) {
        checkNotNull(allocations);
        linkResourceAllocationsMap.put(allocations.intentId(), allocations);
        for (Link link : allocations.links()) {
            subtractFreeResources(link, allocations);
            Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
            if (linkAllocs == null) {
                linkAllocs = new HashSet<>();
            }
            linkAllocs.add(allocations);
            allocatedResources.put(link, linkAllocs);
        }
    }

    @Override
    public synchronized LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
        checkNotNull(allocations);
        linkResourceAllocationsMap.remove(allocations.intentId());
        for (Link link : allocations.links()) {
            addFreeResources(link, allocations);
            Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link);
            if (linkAllocs == null) {
                log.error("Missing resource allocation.");
            } else {
                linkAllocs.remove(allocations);
            }
            allocatedResources.put(link, linkAllocs);
        }

        final List<LinkResourceAllocations> releasedResources =
                ImmutableList.of(allocations);

        return new LinkResourceEvent(
                LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
                releasedResources);
    }

    @Override
    public synchronized LinkResourceAllocations getAllocations(IntentId intentId) {
        checkNotNull(intentId);
        return linkResourceAllocationsMap.get(intentId);
    }

    @Override
    public synchronized Iterable<LinkResourceAllocations> getAllocations(Link link) {
        checkNotNull(link);
        Set<LinkResourceAllocations> result = allocatedResources.get(link);
        if (result == null) {
            result = Collections.emptySet();
        }
        return Collections.unmodifiableSet(result);
    }

    @Override
    public synchronized Iterable<LinkResourceAllocations> getAllocations() {
        return Collections.unmodifiableCollection(linkResourceAllocationsMap.values());
    }


}
