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

public class MessageDispatcherTest extends FloodlightTestCase {

    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();
        System.out.print("Ordering: ");
        for (IOFMessageListener l : result) {
            System.out.print(l.getName());
            System.out.print(",");
        }
        System.out.print("\n");

        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);
    }
}
