/*
 * Copyright 2015-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.dhcp.impl;

import com.google.common.collect.ImmutableSet;
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.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.dhcp.DhcpStore;
import org.onosproject.dhcp.IpAssignment;
import org.onosproject.net.HostId;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;

import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Assigned;
import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;

/**
 * Manages the pool of available IP Addresses in the network and
 * Remembers the mapping between MAC ID and IP Addresses assigned.
 */

@Component(immediate = true)
@Service
public class DistributedDhcpStore implements DhcpStore {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    private ConsistentMap<HostId, IpAssignment> allocationMap;
    private DistributedSet<Ip4Address> freeIPPool;

    private static Ip4Address startIPRange;
    private static Ip4Address endIPRange;

    // Hardcoded values are default values.
    private static int timeoutForPendingAssignments = 60;

    @Activate
    protected void activate() {
        allocationMap = storageService.<HostId, IpAssignment>consistentMapBuilder()
                .withName("onos-dhcp-assignedIP")
                .withSerializer(Serializer.using(
                        new KryoNamespace.Builder()
                                .register(KryoNamespaces.API)
                                .register(IpAssignment.class,
                                        IpAssignment.AssignmentStatus.class,
                                        Date.class)
                                .build("dhcp")))
                .build();

        freeIPPool = storageService.<Ip4Address>setBuilder()
                .withName("onos-dhcp-freeIP")
                .withSerializer(Serializer.using(KryoNamespaces.API))
                .build()
                .asDistributedSet();

        log.info("Started");
    }

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

    @Override
    public Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP) {

        IpAssignment assignmentInfo;
        if (allocationMap.containsKey(hostId)) {
            assignmentInfo = allocationMap.get(hostId).value();
            IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus();
            Ip4Address ipAddr = assignmentInfo.ipAddress();

            if (assignmentInfo.assignmentStatus().equals(Option_RangeNotEnforced)) {
                return assignmentInfo.ipAddress();
            } else if (status == Option_Assigned ||
                    status == IpAssignment.AssignmentStatus.Option_Requested) {
                // Client has a currently Active Binding.
                if (ipWithinRange(ipAddr)) {
                    return ipAddr;
                }

            } else if (status == IpAssignment.AssignmentStatus.Option_Expired) {
                // Client has a Released or Expired Binding.
                if (freeIPPool.contains(ipAddr)) {
                    assignmentInfo = IpAssignment.builder()
                            .ipAddress(ipAddr)
                            .timestamp(new Date())
                            .leasePeriod(timeoutForPendingAssignments)
                            .assignmentStatus(IpAssignment.AssignmentStatus.Option_Requested)
                            .build();
                    if (freeIPPool.remove(ipAddr)) {
                        allocationMap.put(hostId, assignmentInfo);
                        return ipAddr;
                    }
                }
            }
        } else if (requestedIP.toInt() != 0) {
            // Client has requested an IP.
            if (freeIPPool.contains(requestedIP)) {
                assignmentInfo = IpAssignment.builder()
                        .ipAddress(requestedIP)
                        .timestamp(new Date())
                        .leasePeriod(timeoutForPendingAssignments)
                        .assignmentStatus(IpAssignment.AssignmentStatus.Option_Requested)
                        .build();
                if (freeIPPool.remove(requestedIP)) {
                    allocationMap.put(hostId, assignmentInfo);
                    return requestedIP;
                }
            }
        }

        // Allocate a new IP from the server's pool of available IP.
        Ip4Address nextIPAddr = fetchNextIP();
        if (nextIPAddr != null) {
            assignmentInfo = IpAssignment.builder()
                    .ipAddress(nextIPAddr)
                    .timestamp(new Date())
                    .leasePeriod(timeoutForPendingAssignments)
                    .assignmentStatus(IpAssignment.AssignmentStatus.Option_Requested)
                    .build();

            allocationMap.put(hostId, assignmentInfo);
        }
        return nextIPAddr;

    }

    @Override
    public boolean assignIP(HostId hostId, IpAssignment ipAssignment) {
        log.trace("Assign IP Called HostId: {}, ipAssignment: {}",
                  hostId, ipAssignment);

        IpAssignment newAssignment = null;
        Versioned<IpAssignment> versionedAssignment = allocationMap.get(hostId);
        Ip4Address requestedIp = ipAssignment.ipAddress();

        if (versionedAssignment == null) {
            // this is new IP assignment of static mapping
            // dynamic assignment is done in suggestIP
            if (ipAssignment.assignmentStatus().equals(Option_RangeNotEnforced)) {
                newAssignment = ipAssignment;
            } else if (freeIPPool.remove(requestedIp)) {
                newAssignment = IpAssignment.builder(ipAssignment)
                        .assignmentStatus(Option_Assigned)
                        .timestamp(new Date())
                        .build();
            } else {
                log.trace("Failed to assign IP for {}", ipAssignment);
                return false;
            }
            log.trace("Assigned {}", newAssignment);
            return allocationMap.putIfAbsent(hostId, newAssignment) == null;
            // TODO: handle the case where map changed.
        } else {
            // this is lease renew or rebinding
            // update assignment status and time stamp, and keep the others
            IpAssignment existingAssignment = versionedAssignment.value();
            if (!existingAssignment.ipAddress().equals(requestedIp)) {
                // return false if existing assignment is not for the
                // requested host
                log.trace("Failed to assign IP for {}", ipAssignment);
                return false;
            }

            switch (existingAssignment.assignmentStatus()) {
                case Option_RangeNotEnforced:
                    newAssignment = IpAssignment.builder(existingAssignment)
                            .timestamp(new Date())
                            .build();
                    break;
                case Option_Expired:
                    if (!freeIPPool.remove(requestedIp)) {
                        // requested IP is expired for this host and reserved to the other host
                        return false;
                    }
                case Option_Assigned:
                case Option_Requested:
                    newAssignment = IpAssignment.builder(existingAssignment)
                            .timestamp(new Date())
                            .assignmentStatus(Option_Assigned)
                            .build();
                    break;
                default:
                    break;
            }
            log.trace("Assigned {}", newAssignment);
            return allocationMap.replace(hostId, versionedAssignment.version(), newAssignment);
        }
    }

    @Override
    public Ip4Address releaseIP(HostId hostId) {
        if (allocationMap.containsKey(hostId)) {
            // If the IP has been assigned with Option_RangeNotEnforced,
            // we do not release the IP address nor remove the host from HostService.
            // Therefore, if the IP is assigned statically, the IP needs to be released statically.
            Versioned<IpAssignment> assignmentVersioned = allocationMap.get(hostId);
            if (Versioned.valueOrNull(assignmentVersioned) != null &&
                    assignmentVersioned.value().assignmentStatus().equals(Option_RangeNotEnforced)) {
                return null;
            }

            IpAssignment newAssignment = IpAssignment.builder(allocationMap.get(hostId).value())
                    .assignmentStatus(IpAssignment.AssignmentStatus.Option_Expired)
                    .build();
            Ip4Address freeIP = newAssignment.ipAddress();
            allocationMap.put(hostId, newAssignment);
            if (ipWithinRange(freeIP)) {
                freeIPPool.add(freeIP);
            }
            return freeIP;
        }
        return null;
    }

    @Override
    public void setDefaultTimeoutForPurge(int timeInSeconds) {
        timeoutForPendingAssignments = timeInSeconds;
    }

    @Override
    public Map<HostId, IpAssignment> listAssignedMapping() {

        Map<HostId, IpAssignment> validMapping = new HashMap<>();
        IpAssignment assignment;
        for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) {
            assignment = entry.getValue().value();
            if (assignment.assignmentStatus() == Option_Assigned
                    || assignment.assignmentStatus() == Option_RangeNotEnforced) {
                validMapping.put(entry.getKey(), assignment);
            }
        }
        return validMapping;
    }

    @Override
    public Map<HostId, IpAssignment> listAllMapping() {
        Map<HostId, IpAssignment> validMapping = new HashMap<>();
        for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) {
            validMapping.put(entry.getKey(), entry.getValue().value());
        }
        return validMapping;
    }

    @Override
    public boolean assignStaticIP(MacAddress macAddress, IpAssignment ipAssignment) {
        HostId host = HostId.hostId(macAddress);
        return assignIP(host, ipAssignment);
    }

    @Override
    public boolean removeStaticIP(MacAddress macID) {
        HostId host = HostId.hostId(macID);
        if (allocationMap.containsKey(host)) {
            IpAssignment assignment = allocationMap.get(host).value();

            if (assignment.assignmentStatus().equals(Option_RangeNotEnforced)) {
                allocationMap.remove(host);
                return true;
            }

            Ip4Address freeIP = assignment.ipAddress();
            if (assignment.leasePeriod() < 0) {
                allocationMap.remove(host);
                if (ipWithinRange(freeIP)) {
                    freeIPPool.add(freeIP);
                }
                return true;
            }
        }
        return false;
    }

    @Override
    public Iterable<Ip4Address> getAvailableIPs() {
        return ImmutableSet.copyOf(freeIPPool);
    }

    @Override
    public void populateIPPoolfromRange(Ip4Address startIP, Ip4Address endIP) {
        // Clear all entries from previous range.
        allocationMap.clear();
        freeIPPool.clear();
        startIPRange = startIP;
        endIPRange = endIP;

        int lastIP = endIP.toInt();
        Ip4Address nextIP;
        for (int loopCounter = startIP.toInt(); loopCounter <= lastIP; loopCounter++) {
            nextIP = Ip4Address.valueOf(loopCounter);
            freeIPPool.add(nextIP);
        }
        log.debug("Updated free IP pool {}:{} size:{}", startIP, endIP, freeIPPool.size());
    }

    @Override
    public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) {
        if (allocationMap.get(hostId) != null) {
            return allocationMap.get(hostId).value();
        } else {
            return null;
        }
    }

    /**
     * Fetches the next available IP from the free pool pf IPs.
     *
     * @return the next available IP address
     */
    private Ip4Address fetchNextIP() {
        for (Ip4Address freeIP : freeIPPool) {
            if (freeIPPool.remove(freeIP)) {
                return freeIP;
            }
        }
        return null;
    }

    /**
     * Returns true if the given ip is within the range of available IPs.
     *
     * @param ip given ip address
     * @return true if within range, false otherwise
     */
    private boolean ipWithinRange(Ip4Address ip) {
        if ((ip.toInt() >= startIPRange.toInt()) && (ip.toInt() <= endIPRange.toInt())) {
            return true;
        }
        return false;
    }
}

