/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.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);
        }
    }
}
