/*
 * Copyright 2017-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.ofagent.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestTools;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.event.Event;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.ofagent.api.OFAgent;
import org.onosproject.ofagent.api.OFAgentEvent;
import org.onosproject.ofagent.api.OFAgentListener;
import org.onosproject.ofagent.api.OFController;
import org.onosproject.store.service.TestStorageService;

import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.onosproject.ofagent.api.OFAgent.State.STARTED;
import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
import static org.onosproject.ofagent.api.OFAgentEvent.Type.*;

/**
 * Junit tests for OFAgent target.
 */
public class OFAgentManagerTest {

    private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
    private static final ControllerNode LOCAL_NODE =
            new DefaultControllerNode(new NodeId("local"), IpAddress.valueOf("127.0.0.1"));

    private static final Set<OFController> CONTROLLER_1 = Sets.newHashSet(
            DefaultOFController.of(
                    IpAddress.valueOf("192.168.0.3"),
                    TpPort.tpPort(6653)));

    private static final Set<OFController> CONTROLLER_2 = Sets.newHashSet(
            DefaultOFController.of(
                    IpAddress.valueOf("192.168.0.3"),
                    TpPort.tpPort(6653)),
            DefaultOFController.of(
                    IpAddress.valueOf("192.168.0.4"),
                    TpPort.tpPort(6653)));

    private static final NetworkId NETWORK_1 = NetworkId.networkId(1);
    private static final NetworkId NETWORK_2 = NetworkId.networkId(2);

    private static final OFAgent OFAGENT_1 = DefaultOFAgent.builder()
            .networkId(NETWORK_1)
            .state(STOPPED)
            .build();

    private static final OFAgent OFAGENT_1_CTRL_1 = DefaultOFAgent.builder()
            .networkId(NETWORK_1)
            .controllers(CONTROLLER_1)
            .state(STOPPED)
            .build();

    private static final OFAgent OFAGENT_1_CTRL_2 = DefaultOFAgent.builder()
            .networkId(NETWORK_1)
            .controllers(CONTROLLER_2)
            .state(STOPPED)
            .build();

    private static final OFAgent OFAGENT_2 = DefaultOFAgent.builder()
            .networkId(NETWORK_2)
            .state(STOPPED)
            .build();

    private final TestOFAgentListener testListener = new TestOFAgentListener();
    private final CoreService mockCoreService = createMock(CoreService.class);
    private final LeadershipService mockLeadershipService = createMock(LeadershipService.class);
    private final VirtualNetworkService mockVirtualNetService = createMock(VirtualNetworkService.class);
    private final ClusterService mockClusterService = createMock(ClusterService.class);

    private OFAgentManager target;
    private DistributedOFAgentStore ofAgentStore;

    @Before
    public void setUp() throws Exception {
        ofAgentStore = new DistributedOFAgentStore();
        TestUtils.setField(ofAgentStore, "coreService", createMock(CoreService.class));
        TestUtils.setField(ofAgentStore, "storageService", new TestStorageService());
        TestUtils.setField(ofAgentStore, "eventExecutor", MoreExecutors.newDirectExecutorService());
        ofAgentStore.activate();

        expect(mockCoreService.registerApplication(anyObject()))
                .andReturn(APP_ID)
                .anyTimes();
        replay(mockCoreService);

        expect(mockClusterService.getLocalNode())
                .andReturn(LOCAL_NODE)
                .anyTimes();
        replay(mockClusterService);

        expect(mockLeadershipService.runForLeadership(anyObject()))
                .andReturn(null)
                .anyTimes();
        mockLeadershipService.addListener(anyObject());
        mockLeadershipService.removeListener(anyObject());
        mockLeadershipService.withdraw(anyObject());
        replay(mockLeadershipService);

        target = new OFAgentManager();
        target.coreService = mockCoreService;
        target.leadershipService = mockLeadershipService;
        target.virtualNetService = mockVirtualNetService;
        target.clusterService = mockClusterService;
        target.ofAgentStore = ofAgentStore;
        target.addListener(testListener);
        target.activate();
    }

    @After
    public void tearDown() {
        target.removeListener(testListener);
        ofAgentStore.deactivate();
        target.deactivate();
        ofAgentStore = null;
        target = null;
    }

    @Test
    public void testCreateAndRemoveAgent() {
        target.createAgent(OFAGENT_1);
        Set<OFAgent> agents = target.agents();
        assertEquals("OFAgent set size did not match", 1, agents.size());

        target.createAgent(OFAGENT_2);
        agents = target.agents();
        assertEquals("OFAgent set size did not match", 2, agents.size());

        target.removeAgent(NETWORK_1);
        agents = target.agents();
        assertEquals("OFAgent set size did not match", 1, agents.size());

        target.removeAgent(NETWORK_2);
        agents = target.agents();
        assertEquals("OFAgent set size did not match", 0, agents.size());

        validateEvents(OFAGENT_CREATED, OFAGENT_CREATED, OFAGENT_REMOVED, OFAGENT_REMOVED);
    }

    @Test(expected = NullPointerException.class)
    public void testCreateNullAgent() {
        target.createAgent(null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testCreateDuplicateAgent() {
        target.createAgent(OFAGENT_1);
        target.createAgent(OFAGENT_1);
    }

    @Test(expected = NullPointerException.class)
    public void testRemoveNullAgent() {
        target.removeAgent(null);
    }

    @Test(expected = IllegalStateException.class)
    public void testRemoveNotFoundAgent() {
        target.removeAgent(NETWORK_1);
    }

    @Test(expected = IllegalStateException.class)
    public void testRemoveStartedAgent() {
        target.createAgent(OFAGENT_1);
        target.startAgent(NETWORK_1);
        target.removeAgent(NETWORK_1);
    }

    @Test
    public void testStartAndStopAgent() {
        target.createAgent(OFAGENT_1);
        target.startAgent(NETWORK_1);
        OFAgent ofAgent = target.agent(NETWORK_1);
        assertEquals("OFAgent state did not match", STARTED, ofAgent.state());

        target.stopAgent(NETWORK_1);
        ofAgent = target.agent(NETWORK_1);
        assertEquals("OFAgent state did not match", STOPPED, ofAgent.state());

        validateEvents(OFAGENT_CREATED, OFAGENT_STARTED, OFAGENT_STOPPED);
    }

    @Test
    public void testAddController() {
        target.createAgent(OFAGENT_1);
        target.updateAgent(OFAGENT_1_CTRL_1);
        OFAgent ofAgent = target.agent(NETWORK_1);
        assertEquals("OFAgent controller did not match", CONTROLLER_1, ofAgent.controllers());

        target.updateAgent(OFAGENT_1_CTRL_2);
        ofAgent = target.agent(NETWORK_1);
        assertEquals("OFAgent controller did not match", CONTROLLER_2, ofAgent.controllers());

        validateEvents(OFAGENT_CREATED, OFAGENT_CONTROLLER_ADDED, OFAGENT_CONTROLLER_ADDED);
    }

    @Test
    public void testRemoveController() {
        target.createAgent(OFAGENT_1_CTRL_2);
        target.updateAgent(OFAGENT_1_CTRL_1);
        OFAgent ofAgent = target.agent(NETWORK_1);
        assertEquals("OFAgent controller did not match", CONTROLLER_1, ofAgent.controllers());

        target.updateAgent(OFAGENT_1);
        ofAgent = target.agent(NETWORK_1);
        assertTrue("OFAgent controller did not match", ofAgent.controllers().isEmpty());

        validateEvents(OFAGENT_CREATED, OFAGENT_CONTROLLER_REMOVED, OFAGENT_CONTROLLER_REMOVED);
    }

    private void validateEvents(Enum... types) {
        int i = 0;
        assertEquals("Number of events does not match", types.length, testListener.events.size());
        for (Event event : testListener.events) {
            assertEquals("Incorrect event received", types[i], event.type());
            i++;
        }
        testListener.events.clear();
    }

    private static class TestOFAgentListener implements OFAgentListener {

        private List<OFAgentEvent> events = Lists.newArrayList();

        @Override
        public void event(OFAgentEvent event) {
            events.add(event);
        }
    }
}
