/**
 *    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    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 net.floodlightcontroller.core.util;

import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.test.FloodlightTestCase;

import org.junit.Test;
import org.openflow.protocol.OFType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MessageDispatcherTest extends FloodlightTestCase {
    private static final Logger log = LoggerFactory.getLogger(MessageDispatcherTest.class);

    IOFMessageListener createLMock(String name) {
        IOFMessageListener mock = createNiceMock(IOFMessageListener.class);
        expect(mock.getName()).andReturn(name).anyTimes();
        return mock;
    }

    void addPrereqs(IOFMessageListener mock, String... deps) {
        for (String dep : deps) {
            expect(mock.isCallbackOrderingPrereq(OFType.PACKET_IN, dep)).andReturn(true).anyTimes();
        }
    }

    void testOrdering(ArrayList<IOFMessageListener> inputListeners) {
        ListenerDispatcher<OFType, IOFMessageListener> ld =
                new ListenerDispatcher<OFType, IOFMessageListener>();

        for (IOFMessageListener l : inputListeners) {
            ld.addListener(OFType.PACKET_IN, l);
        }
        for (IOFMessageListener l : inputListeners) {
            verify(l);
        }

        List<IOFMessageListener> result = ld.getOrderedListeners();
        StringWriter sw = new StringWriter();
        PrintWriter out = new PrintWriter(sw);

        out.print("Ordering: ");
        for (IOFMessageListener l : result) {
            out.print(l.getName());
            out.print(",");
        }
        out.print("\n");
        log.debug(sw.toString());

        for (int ind_i = 0; ind_i < result.size(); ind_i++) {
            IOFMessageListener i = result.get(ind_i);
            for (int ind_j = ind_i + 1; ind_j < result.size(); ind_j++) {
                IOFMessageListener j = result.get(ind_j);

                boolean orderwrong =
                        (i.isCallbackOrderingPrereq(OFType.PACKET_IN, j.getName()) ||
                                j.isCallbackOrderingPostreq(OFType.PACKET_IN, i.getName()));
                assertFalse("Invalid order: " +
                        ind_i + " (" + i.getName() + ") " +
                        ind_j + " (" + j.getName() + ") ", orderwrong);
            }
        }
    }

    void randomTestOrdering(ArrayList<IOFMessageListener> mocks) {
        Random rand = new Random(0);
        ArrayList<IOFMessageListener> random =
                new ArrayList<IOFMessageListener>();
        random.addAll(mocks);
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < random.size(); j++) {
                int ind = rand.nextInt(mocks.size() - 1);
                IOFMessageListener tmp = random.get(j);
                random.set(j, random.get(ind));
                random.set(ind, tmp);
            }
            testOrdering(random);
        }
    }

    @Test
    public void testCallbackOrderingSimple() throws Exception {
        ArrayList<IOFMessageListener> mocks =
                new ArrayList<IOFMessageListener>();
        for (int i = 0; i < 10; i++) {
            mocks.add(createLMock("" + i));
        }
        for (int i = 1; i < 10; i++) {
            addPrereqs(mocks.get(i), "" + (i - 1));
        }
        for (IOFMessageListener l : mocks) {
            replay(l);
        }
        randomTestOrdering(mocks);
    }

    @Test
    public void testCallbackOrderingPartial() throws Exception {
        ArrayList<IOFMessageListener> mocks =
                new ArrayList<IOFMessageListener>();
        for (int i = 0; i < 10; i++) {
            mocks.add(createLMock("" + i));
        }
        for (int i = 1; i < 5; i++) {
            addPrereqs(mocks.get(i), "" + (i - 1));
        }
        for (int i = 6; i < 10; i++) {
            addPrereqs(mocks.get(i), "" + (i - 1));
        }
        for (IOFMessageListener l : mocks) {
            replay(l);
        }
        randomTestOrdering(mocks);
    }


    @Test
    public void testCallbackOrderingPartial2() throws Exception {
        ArrayList<IOFMessageListener> mocks =
                new ArrayList<IOFMessageListener>();
        for (int i = 0; i < 10; i++) {
            mocks.add(createLMock("" + i));
        }
        for (int i = 2; i < 5; i++) {
            addPrereqs(mocks.get(i), "" + (i - 1));
        }
        for (int i = 6; i < 9; i++) {
            addPrereqs(mocks.get(i), "" + (i - 1));
        }
        for (IOFMessageListener l : mocks) {
            replay(l);
        }
        randomTestOrdering(mocks);
    }
}
