package org.onosproject.sdnip;

import java.util.LinkedList;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.easymock.IArgumentMatcher;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.intent.IntentOperation;
import org.onosproject.net.intent.IntentOperations;
import org.onosproject.sdnip.IntentSynchronizer.IntentKey;

import static org.easymock.EasyMock.reportMatcher;

/**
 * Helper class for testing operations submitted to the IntentService.
 */
public final class TestIntentServiceHelper {
    /**
     * Default constructor to prevent instantiation.
     */
    private TestIntentServiceHelper() {
    }

    /**
     * Matcher method to set the expected intent to match against
     * (ignoring the intent ID for the intent).
     *
     * @param intent the expected Intent
     * @return the submitted Intent
     */
    static Intent eqExceptId(Intent intent) {
        reportMatcher(new IdAgnosticIntentMatcher(intent));
        return intent;
    }

    /**
     * Matcher method to set the expected intent operations to match against
     * (ignoring the intent ID for each intent).
     *
     * @param intentOperations the expected Intent Operations
     * @return the submitted Intent Operations
     */
    static IntentOperations eqExceptId(IntentOperations intentOperations) {
        reportMatcher(new IdAgnosticIntentOperationsMatcher(intentOperations));
        return intentOperations;
    }

    /*
     * EasyMock matcher that matches {@link Intent} but
     * ignores the {@link IntentId} when matching.
     * <p/>
     * The normal intent equals method tests that the intent IDs are equal,
     * however in these tests we can't know what the intent IDs will be in
     * advance, so we can't set up expected intents with the correct IDs. Thus,
     * the solution is to use an EasyMock matcher that verifies that all the
     * value properties of the provided intent match the expected values, but
     * ignores the intent ID when testing equality.
     */
    private static final class IdAgnosticIntentMatcher implements
                IArgumentMatcher {

        private final Intent intent;
        private String providedString;

        /**
         * Constructor taking the expected intent to match against.
         *
         * @param intent the expected intent
         */
        public IdAgnosticIntentMatcher(Intent intent) {
            this.intent = intent;
        }

        @Override
        public void appendTo(StringBuffer strBuffer) {
            strBuffer.append("IntentMatcher unable to match: "
                    + providedString);
        }

        @Override
        public boolean matches(Object object) {
            if (!(object instanceof Intent)) {
                return false;
            }

            Intent providedIntent = (Intent) object;
            providedString = providedIntent.toString();

            IntentKey thisIntentKey = new IntentKey(intent);
            IntentKey providedIntentKey = new IntentKey(providedIntent);
            return thisIntentKey.equals(providedIntentKey);
        }
    }

    /*
     * EasyMock matcher that matches {@link IntenOperations} but
     * ignores the {@link IntentId} when matching.
     * <p/>
     * The normal intent equals method tests that the intent IDs are equal,
     * however in these tests we can't know what the intent IDs will be in
     * advance, so we can't set up expected intents with the correct IDs. Thus,
     * the solution is to use an EasyMock matcher that verifies that all the
     * value properties of the provided intent match the expected values, but
     * ignores the intent ID when testing equality.
     */
    private static final class IdAgnosticIntentOperationsMatcher implements
                IArgumentMatcher {

        private final IntentOperations intentOperations;
        private String providedString;

        /**
         * Constructor taking the expected intent operations to match against.
         *
         * @param intentOperations the expected intent operations
         */
        public IdAgnosticIntentOperationsMatcher(
                        IntentOperations intentOperations) {
            this.intentOperations = intentOperations;
        }

        @Override
        public void appendTo(StringBuffer strBuffer) {
            strBuffer.append("IntentOperationsMatcher unable to match: "
                    + providedString);
        }

        @Override
        public boolean matches(Object object) {
            if (!(object instanceof IntentOperations)) {
                return false;
            }

            IntentOperations providedIntentOperations =
                (IntentOperations) object;
            providedString = providedIntentOperations.toString();

            List<IntentKey> thisSubmitIntents = new LinkedList<>();
            List<IntentId> thisWithdrawIntentIds = new LinkedList<>();
            List<IntentKey> thisReplaceIntents = new LinkedList<>();
            List<IntentKey> thisUpdateIntents = new LinkedList<>();
            List<IntentKey> providedSubmitIntents = new LinkedList<>();
            List<IntentId> providedWithdrawIntentIds = new LinkedList<>();
            List<IntentKey> providedReplaceIntents = new LinkedList<>();
            List<IntentKey> providedUpdateIntents = new LinkedList<>();

            extractIntents(intentOperations, thisSubmitIntents,
                           thisWithdrawIntentIds, thisReplaceIntents,
                           thisUpdateIntents);
            extractIntents(providedIntentOperations, providedSubmitIntents,
                           providedWithdrawIntentIds, providedReplaceIntents,
                           providedUpdateIntents);

            return CollectionUtils.isEqualCollection(thisSubmitIntents,
                                                     providedSubmitIntents) &&
                CollectionUtils.isEqualCollection(thisWithdrawIntentIds,
                                                  providedWithdrawIntentIds) &&
                CollectionUtils.isEqualCollection(thisUpdateIntents,
                                                  providedUpdateIntents) &&
                CollectionUtils.isEqualCollection(thisReplaceIntents,
                                                  providedReplaceIntents);
        }

        /**
         * Extracts the intents per operation type. Each intent is encapsulated
         * in IntentKey so it can be compared by excluding the Intent ID.
         *
         * @param intentOperations the container with the intent operations
         * to extract the intents from
         * @param submitIntents the SUBMIT intents
         * @param withdrawIntentIds the WITHDRAW intents IDs
         * @param replaceIntents the REPLACE intents
         * @param updateIntents the UPDATE intens
         */
        private void extractIntents(IntentOperations intentOperations,
                                    List<IntentKey> submitIntents,
                                    List<IntentId> withdrawIntentIds,
                                    List<IntentKey> replaceIntents,
                                    List<IntentKey> updateIntents) {
            for (IntentOperation oper : intentOperations.operations()) {
                IntentId intentId;
                IntentKey intentKey;
                switch (oper.type()) {
                case SUBMIT:
                    intentKey = new IntentKey(oper.intent());
                    submitIntents.add(intentKey);
                    break;
                case WITHDRAW:
                    intentId = oper.intentId();
                    withdrawIntentIds.add(intentId);
                    break;
                case REPLACE:
                    intentKey = new IntentKey(oper.intent());
                    replaceIntents.add(intentKey);
                    break;
                case UPDATE:
                    intentKey = new IntentKey(oper.intent());
                    updateIntents.add(intentKey);
                    break;
                default:
                    break;
                }
            }
        }
    }
}
