package org.onlab.onos.sdnip;

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

import org.apache.commons.collections4.CollectionUtils;
import org.easymock.IArgumentMatcher;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentOperation;
import org.onlab.onos.net.intent.IntentOperations;
import org.onlab.onos.net.intent.PointToPointIntent;
import org.onlab.onos.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 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;
    }


    /**
     * Matcher method to set an expected point-to-point intent to match
     * against (ignoring the intent ID).
     *
     * @param intent the expected point-to-point intent
     * @return the submitted point-to-point intent
     */
    private static PointToPointIntent eqExceptId(
            PointToPointIntent intent) {
        reportMatcher(new IdAgnosticPointToPointIntentMatcher(intent));
        return intent;
    }

    /*
     * 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;
                }
            }
        }
    }

    /*
     * EasyMock matcher that matches {@link PointToPointIntent}s 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 IdAgnosticPointToPointIntentMatcher implements
                IArgumentMatcher {

        private final PointToPointIntent intent;
        private String providedIntentString;

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

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

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

            PointToPointIntent providedIntent = (PointToPointIntent) object;
            providedIntentString = providedIntent.toString();

            PointToPointIntent matchIntent =
                    new PointToPointIntent(providedIntent.appId(),
                            intent.selector(), intent.treatment(),
                            intent.ingressPoint(), intent.egressPoint());

            return matchIntent.equals(providedIntent);
        }
    }
}
