/*
 * Copyright 2015-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.provider.nil;

import com.google.common.collect.Sets;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.TimerTask;
import org.onlab.util.Timer;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.CompletedBatchOperation;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleBatchEntry;
import org.onosproject.net.flow.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderService;
import org.slf4j.Logger;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Null provider to accept any flow and report them.
 */
class NullFlowRuleProvider extends NullProviders.AbstractNullProvider
        implements FlowRuleProvider {

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

    private ConcurrentMap<DeviceId, Set<FlowEntry>> flowTable = new ConcurrentHashMap<>();

    private FlowRuleProviderService providerService;

    private HashedWheelTimer timer = Timer.getTimer();
    private Timeout timeout;

    /**
     * Starts the flow rule provider simulation.
     *
     * @param providerService flow rule provider service
     */
    void start(FlowRuleProviderService providerService) {
        this.providerService = providerService;
        timeout = timer.newTimeout(new StatisticTask(), 5, TimeUnit.SECONDS);
    }

    /**
     * Stops the flow rule provider simulation.
     */
    void stop() {
        timeout.cancel();
    }

    @Override
    public void applyFlowRule(FlowRule... flowRules) {
        // FIXME: invoke executeBatch
    }

    @Override
    public void removeFlowRule(FlowRule... flowRules) {
        // FIXME: invoke executeBatch
    }

    @Override
    public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
        throw new UnsupportedOperationException("Cannot remove by appId from null provider");
    }

    @Override
    public void executeBatch(FlowRuleBatchOperation batch) {
        // TODO: consider checking mastership
        Set<FlowEntry> entries =
                flowTable.getOrDefault(batch.deviceId(),
                                       Sets.newConcurrentHashSet());
        for (FlowRuleBatchEntry fbe : batch.getOperations()) {
            switch (fbe.operator()) {
                case ADD:
                    entries.add(new DefaultFlowEntry(fbe.target()));
                    break;
                case REMOVE:
                    entries.remove(new DefaultFlowEntry(fbe.target()));
                    break;
                case MODIFY:
                    FlowEntry entry = new DefaultFlowEntry(fbe.target());
                    entries.remove(entry);
                    entries.add(entry);
                    break;
                default:
                    log.error("Unknown flow operation: {}", fbe);
            }
        }
        flowTable.put(batch.deviceId(), entries);
        CompletedBatchOperation op =
                new CompletedBatchOperation(true, Collections.emptySet(),
                                            batch.deviceId());
        providerService.batchOperationCompleted(batch.id(), op);
    }

    // Periodically reports flow rule statistics.
    private class StatisticTask implements TimerTask {
        @Override
        public void run(Timeout to) throws Exception {
            for (DeviceId devId : flowTable.keySet()) {
                Set<FlowEntry> entries =
                        flowTable.getOrDefault(devId, Collections.emptySet());
                providerService.pushFlowMetrics(devId, entries);
            }
            timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS);
        }
    }
}
