/*
 * 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.net.intent.impl.installer;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.intent.FlowObjectiveIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentInstallationContext;
import org.onosproject.net.intent.IntentOperationContext;
import org.onosproject.net.intent.IntentState;
import org.onosproject.store.service.WallClockTimestamp;

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

import static org.junit.Assert.*;
import static org.onosproject.net.flowobjective.ObjectiveError.*;

/**
 * Tests for flow objective Intent installer.
 */
public class FlowObjectiveIntentInstallerTest extends AbstractIntentInstallerTest {
    private static final int NEXT_ID_1 = 1;
    protected FlowObjectiveIntentInstaller installer;
    protected TestFlowObjectiveService flowObjectiveService;

    @Before
    public void setup() {
        super.setup();
        flowObjectiveService = new TestFlowObjectiveService();
        installer = new FlowObjectiveIntentInstaller();
        installer.flowObjectiveService = flowObjectiveService;
        installer.trackerService = trackerService;
        installer.intentExtensionService = intentExtensionService;
        installer.intentInstallCoordinator = intentInstallCoordinator;

        installer.activate();
    }

    @After
    public void tearDown() {
        super.tearDown();
        installer.deactivated();
    }

    /**
     * Installs flow objective Intents.
     */
    @Test
    public void testInstallIntent() {
        List<Intent> intentsToUninstall = Lists.newArrayList();
        List<Intent> intentsToInstall = createFlowObjectiveIntents();

        IntentData toUninstall = null;
        IntentData toInstall = new IntentData(createP2PIntent(),
                                              IntentState.INSTALLING,
                                              new WallClockTimestamp());
        toInstall = IntentData.compiled(toInstall, intentsToInstall);


        IntentOperationContext<FlowObjectiveIntent> operationContext;
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);

        installer.apply(operationContext);

        IntentOperationContext successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, operationContext);
    }

    /**
     * Uninstalls flow objective Intents.
     */
    @Test
    public void testUninstallIntent() {
        List<Intent> intentsToUninstall = createFlowObjectiveIntents();
        List<Intent> intentsToInstall = Lists.newArrayList();


        IntentData toInstall = null;
        IntentData toUninstall = new IntentData(createP2PIntent(),
                                              IntentState.WITHDRAWING,
                                              new WallClockTimestamp());
        toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
        IntentOperationContext<FlowObjectiveIntent> operationContext;
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);

        installer.apply(operationContext);

        IntentOperationContext successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, operationContext);
    }

    /**
     * Do both uninstall and install flow objective Intents.
     */
    @Test
    public void testUninstallAndInstallIntent() {
        List<Intent> intentsToUninstall = createFlowObjectiveIntents();
        List<Intent> intentsToInstall = createAnotherFlowObjectiveIntents();
        IntentData toInstall = new IntentData(createP2PIntent(),
                                              IntentState.INSTALLING,
                                              new WallClockTimestamp());
        toInstall = IntentData.compiled(toInstall, intentsToInstall);
        IntentData toUninstall = new IntentData(createP2PIntent(),
                                                IntentState.INSTALLED,
                                                new WallClockTimestamp());
        toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);

        IntentOperationContext<FlowObjectiveIntent> operationContext;
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);

        installer.apply(operationContext);

        IntentOperationContext successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, operationContext);
    }

    /**
     * Nothing to uninstall or install.
     */
    @Test
    public void testNoAnyIntentToApply() {
        IntentData toInstall = null;
        IntentData toUninstall = null;
        IntentOperationContext<FlowObjectiveIntent> operationContext;
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
        installer.apply(operationContext);

        IntentOperationContext successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, operationContext);
    }

    /*
     * Error handling
     */
    IntentOperationContext context;
    IntentOperationContext failedContext;
    IntentOperationContext successContext;
    List<ObjectiveError> errors;

    /**
     * Handles UNSUPPORTED error.
     */
    @Test
    public void testUnsupportedError() {
        // Unsupported, should just failed
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        installer.flowObjectiveService = new TestFailedFlowObjectiveService();
        context = createInstallContext();
        installer.apply(context);
        assertEquals(intentInstallCoordinator.failedContext, context);
    }

    /**
     * Handles FLOWINSTALLATIONFAILED error with touch the threshold.
     */
    @Test
    public void testFlowInstallationFailedError() {
        // flow install failed, should retry until retry threshold
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
                                  FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
                                  FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
                                  FLOWINSTALLATIONFAILED);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        failedContext = intentInstallCoordinator.failedContext;
        assertEquals(failedContext, context);
    }

    /**
     * Handles FLOWINSTALLATIONFAILED error without touch the threshold.
     */
    @Test
    public void testFlowInstallationFailedErrorUnderThreshold() {
        // And retry two times and success
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);
    }

    /**
     * Handles GROUPINSTALLATIONFAILED error with touch the threshold.
     */
    @Test
    public void testGroupInstallationFailedError() {
        // Group install failed, and retry threshold exceed
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
                                  GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
                                  GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
                                  GROUPINSTALLATIONFAILED);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        failedContext = intentInstallCoordinator.failedContext;
        assertEquals(failedContext, context);

    }

    /**
     * Handles GROUPINSTALLATIONFAILED error without touch the threshold.
     */
    @Test
    public void testGroupInstallationFailedErrorUnderThreshold() {
        // group install failed, and retry two times.
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);

    }

    /**
     * Handles GROUPEXISTS error.
     */
    @Test
    public void testGroupExistError() {
        // group exists, retry by using add to exist
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPEXISTS);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);
    }

    /**
     * Handles GROUPMISSING error with ADD_TO_EXIST operation.
     */
    @Test
    public void testGroupMissingError() {
        // group exist -> group missing -> add group
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPEXISTS, GROUPMISSING);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);
    }

    /**
     * Handles GROUPMISSING error with ADD operation.
     */
    @Test
    public void testGroupChainElementMissingError() {
        // group chain element missing
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPMISSING);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createInstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);
    }

    /**
     * Handles GROUPMISSING error with REMOVE operation.
     */
    @Test
    public void testGroupAlreadyRemoved() {
        // group already removed
        intentInstallCoordinator = new TestIntentInstallCoordinator();
        installer.intentInstallCoordinator = intentInstallCoordinator;
        errors = ImmutableList.of(GROUPMISSING);
        installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
        context = createUninstallContext();
        installer.apply(context);
        successContext = intentInstallCoordinator.successContext;
        assertEquals(successContext, context);
    }

    /**
     * Creates Intent operation context for uninstall Intents.
     *
     * @return the context
     */
    private IntentOperationContext createUninstallContext() {
        List<Intent> intentsToUninstall = createFlowObjectiveIntents();
        List<Intent> intentsToInstall = Lists.newArrayList();
        IntentData toInstall = null;
        IntentData toUninstall = new IntentData(createP2PIntent(),
                                              IntentState.INSTALLING,
                                              new WallClockTimestamp());
        toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
    }

    /**
     * Creates Intent operation context for install Intents.
     *
     * @return the context
     */
    private IntentOperationContext createInstallContext() {
        List<Intent> intentsToUninstall = Lists.newArrayList();
        List<Intent> intentsToInstall = createFlowObjectiveIntents();
        IntentData toUninstall = null;
        IntentData toInstall = new IntentData(createP2PIntent(),
                                              IntentState.INSTALLING,
                                              new WallClockTimestamp());
        toInstall = IntentData.compiled(toInstall, intentsToInstall);
        IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
        return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
    }

    /**
     * Creates flow objective Intents.
     *
     * @return the flow objective intents
     */
    private List<Intent> createFlowObjectiveIntents() {
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchInPort(CP1.port())
                .build();
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(CP2.port())
                .build();

        FilteringObjective filt = DefaultFilteringObjective.builder()
                .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(APP_ID)
                .permit()
                .add();

        NextObjective next = DefaultNextObjective.builder()
                .withMeta(selector)
                .addTreatment(treatment)
                .makePermanent()
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(APP_ID)
                .withType(NextObjective.Type.SIMPLE)
                .withId(NEXT_ID_1)
                .add();

        ForwardingObjective fwd = DefaultForwardingObjective.builder()
                .withSelector(selector)
                .fromApp(APP_ID)
                .withPriority(DEFAULT_PRIORITY)
                .makePermanent()
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .nextStep(NEXT_ID_1)
                .add();

        List<Objective> objectives = ImmutableList.of(filt, next, fwd);
        List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
        List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());

        Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
        return ImmutableList.of(intent);
    }

    /**
     * Creates flow objective Intents with different selector.
     *
     * @return the flow objective Intents
     */
    private List<Intent> createAnotherFlowObjectiveIntents() {
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchVlanId(VlanId.vlanId("100"))
                .matchInPort(CP1.port())
                .build();
        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(CP2.port())
                .build();

        FilteringObjective filt = DefaultFilteringObjective.builder()
                .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
                .addCondition(selector.getCriterion(Criterion.Type.VLAN_VID))
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(APP_ID)
                .permit()
                .add();

        NextObjective next = DefaultNextObjective.builder()
                .withMeta(selector)
                .addTreatment(treatment)
                .makePermanent()
                .withPriority(DEFAULT_PRIORITY)
                .fromApp(APP_ID)
                .withType(NextObjective.Type.SIMPLE)
                .withId(NEXT_ID_1)
                .add();

        ForwardingObjective fwd = DefaultForwardingObjective.builder()
                .withSelector(selector)
                .fromApp(APP_ID)
                .withPriority(DEFAULT_PRIORITY)
                .makePermanent()
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .nextStep(NEXT_ID_1)
                .add();

        List<Objective> objectives = ImmutableList.of(filt, next, fwd);
        List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
        List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());

        Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
        return ImmutableList.of(intent);
    }

    /**
     * Flow objective service for test; always successful for every flow objectives.
     */
    class TestFlowObjectiveService extends FlowObjectiveServiceAdapter {
        List<DeviceId> devices = Lists.newArrayList();
        List<Objective> objectives = Lists.newArrayList();

        @Override
        public void apply(DeviceId deviceId, Objective objective) {
            devices.add(deviceId);
            objectives.add(objective);
            objective.context().ifPresent(context -> context.onSuccess(objective));
        }
    }

    /**
     * Flow objective service for test; contains errors for every flow objective
     * submission.
     */
    class TestFailedFlowObjectiveService extends TestFlowObjectiveService {
        private final Set<ObjectiveError> groupErrors =
                ImmutableSet.of(GROUPEXISTS, GROUPINSTALLATIONFAILED,
                                GROUPMISSING, GROUPREMOVALFAILED);

        /**
         * Error states to test error handler by given error queue
         * e.g.
         * FLOWINSTALLATIONFAILED -> FLOWINSTALLATIONFAILED -> null: should be success
         * FLOWINSTALLATIONFAILED -> five same error -> ....       : should be failed
         */
        List<ObjectiveError> errors;

        public TestFailedFlowObjectiveService() {
            errors = Lists.newArrayList();
            errors.add(UNSUPPORTED);
        }

        public TestFailedFlowObjectiveService(List<ObjectiveError> errors) {
            this.errors = Lists.newArrayList(errors);
        }

        @Override
        public void apply(DeviceId deviceId, Objective objective) {
            if (errors.size() != 0) {
                if (groupErrors.contains(errors.get(0)) && objective instanceof NextObjective) {
                    ObjectiveError error = errors.remove(0);
                    objective.context().ifPresent(context -> context.onError(objective, error));
                    return;
                }
                if (!groupErrors.contains(errors.get(0)) && !(objective instanceof NextObjective)) {
                    ObjectiveError error = errors.remove(0);
                    objective.context().ifPresent(context -> context.onError(objective, error));
                    return;
                }
            }
            objective.context().ifPresent(context -> context.onSuccess(objective));

        }
    }
}
