/*
 * 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.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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

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 = DhcpStore.class)
public class DistributedDhcpStore implements DhcpStore {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    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;
    }
}

