/*
 * 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.net.flow.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.onosproject.core.ApplicationId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.CompletedBatchOperation;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleBatchEntry;
import org.onosproject.net.flow.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import static com.google.common.collect.ImmutableSet.copyOf;
import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.*;

/**
 * Driver-based flow rule provider.
 */
class FlowRuleDriverProvider extends AbstractProvider implements FlowRuleProvider {

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

    // Perhaps to be extracted for better reuse as we deal with other.
    public static final String SCHEME = "default";
    public static final String PROVIDER_NAME = "org.onosproject.provider";

    FlowRuleProviderService providerService;
    private DeviceService deviceService;
    private MastershipService mastershipService;

    private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    private ScheduledFuture<?> poller = null;

    /**
     * Creates a new fallback flow rule provider.
     */
    FlowRuleDriverProvider() {
        super(new ProviderId(SCHEME, PROVIDER_NAME));
    }

    /**
     * Initializes the provider with necessary supporting services.
     *
     * @param providerService   flow rule provider service
     * @param deviceService     device service
     * @param mastershipService mastership service
     * @param pollFrequency     flow entry poll frequency
     */
    void init(FlowRuleProviderService providerService,
              DeviceService deviceService, MastershipService mastershipService,
              int pollFrequency) {
        this.providerService = providerService;
        this.deviceService = deviceService;
        this.mastershipService = mastershipService;

        if (poller != null && !poller.isCancelled()) {
            poller.cancel(false);
        }

        poller = executor.scheduleAtFixedRate(this::pollFlowEntries, pollFrequency,
                                              pollFrequency, TimeUnit.SECONDS);
    }

    @Override
    public void applyFlowRule(FlowRule... flowRules) {
        rulesByDevice(flowRules).asMap().forEach(this::applyFlowRules);
    }

    @Override
    public void removeFlowRule(FlowRule... flowRules) {
        rulesByDevice(flowRules).asMap().forEach(this::removeFlowRules);
    }

    @Override
    public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
        removeFlowRule(flowRules);
    }

    @Override
    public void executeBatch(FlowRuleBatchOperation batch) {
        ImmutableList.Builder<FlowRule> toAdd = ImmutableList.builder();
        ImmutableList.Builder<FlowRule> toRemove = ImmutableList.builder();
        for (FlowRuleBatchEntry fbe : batch.getOperations()) {
            if (fbe.operator() == ADD || fbe.operator() == MODIFY) {
                toAdd.add(fbe.target());
            } else if (fbe.operator() == REMOVE) {
                toRemove.add(fbe.target());
            }
        }

        ImmutableList<FlowRule> rulesToAdd = toAdd.build();
        ImmutableList<FlowRule> rulesToRemove = toRemove.build();

        Collection<FlowRule> added = applyFlowRules(batch.deviceId(), rulesToAdd);
        Collection<FlowRule> removed = removeFlowRules(batch.deviceId(), rulesToRemove);

        Set<FlowRule> failedRules = Sets.union(Sets.difference(copyOf(rulesToAdd), copyOf(added)),
                                               Sets.difference(copyOf(rulesToRemove), copyOf(removed)));
        CompletedBatchOperation status =
                new CompletedBatchOperation(failedRules.isEmpty(), failedRules, batch.deviceId());
        providerService.batchOperationCompleted(batch.id(), status);
    }

    private Multimap<DeviceId, FlowRule> rulesByDevice(FlowRule[] flowRules) {
        // Sort the flow rules by device id
        Multimap<DeviceId, FlowRule> rulesByDevice = LinkedListMultimap.create();
        for (FlowRule rule : flowRules) {
            rulesByDevice.put(rule.deviceId(), rule);
        }
        return rulesByDevice;
    }

    private Collection<FlowRule> applyFlowRules(DeviceId deviceId, Collection<FlowRule> flowRules) {
        FlowRuleProgrammable programmer = getFlowRuleProgrammable(deviceId);
        return programmer != null ? programmer.applyFlowRules(flowRules) : ImmutableList.of();
    }

    private Collection<FlowRule> removeFlowRules(DeviceId deviceId, Collection<FlowRule> flowRules) {
        FlowRuleProgrammable programmer = getFlowRuleProgrammable(deviceId);
        return programmer != null ? programmer.removeFlowRules(flowRules) : ImmutableList.of();
    }

    private FlowRuleProgrammable getFlowRuleProgrammable(DeviceId deviceId) {
        Device device = deviceService.getDevice(deviceId);
        if (device.is(FlowRuleProgrammable.class)) {
            return device.as(FlowRuleProgrammable.class);
        } else {
            log.debug("Device {} is not flow rule programmable", deviceId);
            return null;
        }
    }


    private void pollFlowEntries() {
        deviceService.getAvailableDevices().forEach(device -> {
            if (mastershipService.isLocalMaster(device.id()) && device.is(FlowRuleProgrammable.class)) {
                providerService.pushFlowMetrics(device.id(),
                                                device.as(FlowRuleProgrammable.class).getFlowEntries());
            }
        });
    }

}
