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

import java.util.Collection;
import java.util.List;

import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentBatchDelegate;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentTestsMocks.MockIntent;
import org.onosproject.net.intent.IntentTestsMocks.MockTimestamp;
import org.onosproject.net.intent.MockIdGenerator;

import com.google.common.collect.ImmutableList;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;

/**
 * Unit tests for the intent accumulator.
 */
public class IntentAccumulatorTest {

    Intent intent1;
    Intent intent2;
    Intent intent3;
    IdGenerator mockGenerator;

    private static IntentDataMatcher containsIntent(Intent intent) {
        return new IntentDataMatcher(intent);
    }

    /**
     * Creates mock intents used by the test.
     */
    @Before
    public void localSetup() {
        mockGenerator = new MockIdGenerator();
        Intent.bindIdGenerator(mockGenerator);

        intent1 = new MockIntent(1L);
        intent2 = new MockIntent(2L);
        intent3 = new MockIntent(3L);
    }

    /**
     * Removes id generator from the Intent class.
     */
    @After
    public void localTearDown() {
        Intent.unbindIdGenerator(mockGenerator);
    }

    /**
     * Hamcrest matcher to check that a collection of intent data objects
     * contains an entry for a given intent.
     */
    private static final class IntentDataMatcher
            extends TypeSafeDiagnosingMatcher<Collection<IntentData>> {

        final Intent intent;

        public IntentDataMatcher(Intent intent) {
            this.intent = intent;
        }

        /**
         * Check that the given collection of intent data contains a specific
         * intent.
         *
         * @param operations  collection of intent data
         * @param description description
         * @return true if the collection contains the intent, false otherwise.
         */
        public boolean matchesSafely(Collection<IntentData> operations,
                                     Description description) {
            for (IntentData operation : operations) {
                if (operation.key().equals(intent.key())) {
                    if (operation.state() != IntentState.INSTALLED) {
                        description.appendText("state was " + operation.state());
                        return false;
                    }
                    return true;
                }
            }
            description.appendText("key was not found " + intent.key());
            return false;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("INSTALLED state intent with key " + intent.key());
        }
    }

    /**
     * Mock batch delegate class.  Gets calls from the accumulator and checks
     * that the operations have been properly compressed.
     */
    private class MockIntentBatchDelegate
                   implements IntentBatchDelegate {
        public void execute(Collection<IntentData> operations) {
            assertThat(operations, hasSize(3));
            assertThat(operations, containsIntent(intent1));
            assertThat(operations, containsIntent(intent2));
            assertThat(operations, containsIntent(intent3));
        }
    }

    /**
     * Tests that the accumulator properly compresses operations on the same
     * intents.
     */
    @Test
    public void checkAccumulator() {

        MockIntentBatchDelegate delegate = new MockIntentBatchDelegate();
        IntentAccumulator accumulator = new IntentAccumulator(delegate);

        List<IntentData> intentDataItems = ImmutableList.of(
                new IntentData(intent1, IntentState.INSTALLING,
                        new MockTimestamp(1)),
                new IntentData(intent2, IntentState.INSTALLING,
                        new MockTimestamp(1)),
                new IntentData(intent3, IntentState.INSTALLED,
                        new MockTimestamp(1)),
                new IntentData(intent2, IntentState.INSTALLED,
                        new MockTimestamp(1)),
                new IntentData(intent2, IntentState.INSTALLED,
                        new MockTimestamp(1)),
                new IntentData(intent1, IntentState.INSTALLED,
                        new MockTimestamp(1)));


        accumulator.processItems(intentDataItems);
    }


}
