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

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

import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.constraint.AnnotationConstraint;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.LambdaConstraint;
import org.onosproject.net.intent.constraint.LatencyConstraint;
import org.onosproject.net.intent.constraint.LinkTypeConstraint;
import org.onosproject.net.intent.constraint.ObstacleConstraint;
import org.onosproject.net.intent.constraint.WaypointConstraint;

import com.fasterxml.jackson.databind.JsonNode;

/**
 * Hamcrest matcher to check that an intent representation in JSON matches
 * the actual intent.
 */
public final class IntentJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {

    private final Intent intent;

    /**
     * Constructor is private, use factory method.
     *
     * @param intentValue the intent object to compare against
     */
    private IntentJsonMatcher(Intent intentValue) {
        intent = intentValue;
    }

    /**
     * Matches the JSON representation of a host to host intent.
     *
     * @param jsonIntent JSON representation of the intent
     * @param description Description object used for recording errors
     * @return true if the JSON matches the intent, false otherwise
     */
    private boolean matchHostToHostIntent(JsonNode jsonIntent, Description description) {
        final HostToHostIntent hostToHostIntent = (HostToHostIntent) intent;

        // check host one
        final String host1 = hostToHostIntent.one().toString();
        final String jsonHost1 = jsonIntent.get("one").asText();
        if (!host1.equals(jsonHost1)) {
            description.appendText("host one was " + jsonHost1);
            return false;
        }

        // check host 2
        final String host2 = hostToHostIntent.two().toString();
        final String jsonHost2 = jsonIntent.get("two").asText();
        if (!host2.equals(jsonHost2)) {
            description.appendText("host two was " + jsonHost2);
            return false;
        }
        return true;
    }

    /**
     * Matches the JSON representation of a point to point intent.
     *
     * @param jsonIntent JSON representation of the intent
     * @param description Description object used for recording errors
     * @return true if the JSON matches the intent, false otherwise
     */
    private boolean matchPointToPointIntent(JsonNode jsonIntent, Description description) {
        final PointToPointIntent pointToPointIntent = (PointToPointIntent) intent;

        // check ingress connection
        final ConnectPoint ingress = pointToPointIntent.ingressPoint();
        final ConnectPointJsonMatcher ingressMatcher =
                ConnectPointJsonMatcher.matchesConnectPoint(ingress);
        final JsonNode jsonIngress = jsonIntent.get("ingressPoint");
        final boolean ingressMatches =
                ingressMatcher.matchesSafely(jsonIngress, description);

        if (!ingressMatches) {
            description.appendText("ingress was " + jsonIngress);
            return false;
        }

        // check egress connection
        final ConnectPoint egress = pointToPointIntent.egressPoint();
        final ConnectPointJsonMatcher egressMatcher =
                ConnectPointJsonMatcher.matchesConnectPoint(egress);
        final JsonNode jsonEgress = jsonIntent.get("egressPoint");
        final boolean egressMatches =
                egressMatcher.matchesSafely(jsonEgress, description);

        if (!egressMatches) {
            description.appendText("egress was " + jsonEgress);
            return false;
        }

        return true;
    }


    /**
     * Matches a bandwidth constraint against a JSON representation of the
     * constraint.
     *
     * @param bandwidthConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchBandwidthConstraint(BandwidthConstraint bandwidthConstraint,
                                             JsonNode constraintJson) {
        final JsonNode bandwidthJson = constraintJson.get("bandwidth");
        return bandwidthJson != null
                && constraintJson.get("bandwidth").asDouble()
                == bandwidthConstraint.bandwidth().bps();
    }

    /**
     * Matches a lamdba constraint against a JSON representation of the
     * constraint.
     *
     * @param lambdaConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchLambdaConstraint(LambdaConstraint lambdaConstraint,
                                          JsonNode constraintJson) {
        final JsonNode lambdaJson = constraintJson.get("lambda");
        return lambdaJson != null
                && constraintJson.get("lambda").asInt()
                == lambdaConstraint.lambda().toInt();
    }

    /**
     * Matches a link type constraint against a JSON representation of the
     * constraint.
     *
     * @param linkTypeConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchLinkTypeConstraint(LinkTypeConstraint linkTypeConstraint,
                                            JsonNode constraintJson) {
        final JsonNode inclusiveJson = constraintJson.get("inclusive");
        final JsonNode typesJson = constraintJson.get("types");

        if (typesJson.size() != linkTypeConstraint.types().size()) {
            return false;
        }

        int foundType = 0;
        for (Link.Type type : linkTypeConstraint.types()) {
            for (int jsonIndex = 0; jsonIndex < typesJson.size(); jsonIndex++) {
                if (type.name().equals(typesJson.get(jsonIndex).asText())) {
                    foundType++;
                    break;
                }
            }
        }
        return (inclusiveJson != null &&
                inclusiveJson.asBoolean() == linkTypeConstraint.isInclusive()) &&
                foundType == typesJson.size();
    }

    /**
     * Matches an annotation constraint against a JSON representation of the
     * constraint.
     *
     * @param annotationConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchAnnotationConstraint(AnnotationConstraint annotationConstraint,
                                              JsonNode constraintJson) {
        final JsonNode keyJson = constraintJson.get("key");
        final JsonNode thresholdJson = constraintJson.get("threshold");
        return (keyJson != null
                && keyJson.asText().equals(annotationConstraint.key())) &&
               (thresholdJson != null
                && thresholdJson.asDouble() == annotationConstraint.threshold());
    }

    /**
     * Matches a latency constraint against a JSON representation of the
     * constraint.
     *
     * @param latencyConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchLatencyConstraint(LatencyConstraint latencyConstraint,
                                           JsonNode constraintJson) {
        final JsonNode latencyJson = constraintJson.get("latencyMillis");
        return (latencyJson != null
                && latencyJson.asInt() == latencyConstraint.latency().toMillis());
    }

    /**
     * Matches an obstacle constraint against a JSON representation of the
     * constraint.
     *
     * @param obstacleConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchObstacleConstraint(ObstacleConstraint obstacleConstraint,
                                            JsonNode constraintJson) {
        final JsonNode obstaclesJson = constraintJson.get("obstacles");

        if (obstaclesJson.size() != obstacleConstraint.obstacles().size()) {
            return false;
        }

        for (int obstaclesIndex = 0; obstaclesIndex < obstaclesJson.size();
                 obstaclesIndex++) {
            boolean obstacleFound = false;
            final String obstacleJson = obstaclesJson.get(obstaclesIndex)
                    .asText();
            for (DeviceId obstacle : obstacleConstraint.obstacles()) {
                if (obstacle.toString().equals(obstacleJson)) {
                    obstacleFound = true;
                }
            }
            if (!obstacleFound) {
                return false;
            }
        }
        return true;
    }

    /**
     * Matches a waypoint constraint against a JSON representation of the
     * constraint.
     *
     * @param waypointConstraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchWaypointConstraint(WaypointConstraint waypointConstraint,
                                            JsonNode constraintJson) {
        final JsonNode waypointsJson = constraintJson.get("waypoints");

        if (waypointsJson.size() != waypointConstraint.waypoints().size()) {
            return false;
        }

        for (int waypointsIndex = 0; waypointsIndex < waypointsJson.size();
             waypointsIndex++) {
            boolean waypointFound = false;
            final String waypointJson = waypointsJson.get(waypointsIndex)
                    .asText();
            for (DeviceId waypoint : waypointConstraint.waypoints()) {
                if (waypoint.toString().equals(waypointJson)) {
                    waypointFound = true;
                }
            }
            if (!waypointFound) {
                return false;
            }
        }
        return true;
    }


    /**
     * Matches a constraint against a JSON representation of the
     * constraint.
     *
     * @param constraint constraint object to match
     * @param constraintJson JSON representation of the constraint
     * @return true if the constraint and JSON match, false otherwise.
     */
    private boolean matchConstraint(Constraint constraint, JsonNode constraintJson) {
        final JsonNode typeJson = constraintJson.get("type");
        if (!typeJson.asText().equals(constraint.getClass().getSimpleName())) {
            return false;
        }
        if (constraint instanceof BandwidthConstraint) {
            return matchBandwidthConstraint((BandwidthConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof LambdaConstraint) {
            return matchLambdaConstraint((LambdaConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof LinkTypeConstraint) {
            return matchLinkTypeConstraint((LinkTypeConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof AnnotationConstraint) {
            return matchAnnotationConstraint((AnnotationConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof LatencyConstraint) {
            return matchLatencyConstraint((LatencyConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof ObstacleConstraint) {
            return matchObstacleConstraint((ObstacleConstraint) constraint,
                    constraintJson);
        } else if (constraint instanceof WaypointConstraint) {
            return matchWaypointConstraint((WaypointConstraint) constraint,
                    constraintJson);
        }
        return true;
    }

    /**
     * Matches the JSON representation of a connectivity intent. Calls the
     * matcher for the connectivity intent subtype.
     *
     * @param jsonIntent JSON representation of the intent
     * @param description Description object used for recording errors
     * @return true if the JSON matches the intent, false otherwise
     */
    private boolean matchConnectivityIntent(JsonNode jsonIntent, Description description) {
        final ConnectivityIntent connectivityIntent = (ConnectivityIntent) intent;

        // check selector
        final JsonNode jsonSelector = jsonIntent.get("selector");
        final TrafficSelector selector = connectivityIntent.selector();
        final Set<Criterion> criteria = selector.criteria();
        final JsonNode jsonCriteria = jsonSelector.get("criteria");
        if (jsonCriteria.size() != criteria.size()) {
            description.appendText("size of criteria array is "
                    + Integer.toString(jsonCriteria.size()));
            return false;
        }

        for (Criterion criterion : criteria) {
            boolean criterionFound = false;
            for (int criterionIndex = 0; criterionIndex < jsonCriteria.size(); criterionIndex++) {
                final CriterionJsonMatcher criterionMatcher =
                        CriterionJsonMatcher.matchesCriterion(criterion);
                if (criterionMatcher.matches(jsonCriteria.get(criterionIndex))) {
                    criterionFound = true;
                    break;
                }
            }
            if (!criterionFound) {
                description.appendText("criterion not found " + criterion.toString());
                return false;
            }
        }

        // check treatment
        final JsonNode jsonTreatment = jsonIntent.get("treatment");
        final TrafficTreatment treatment = connectivityIntent.treatment();
        final List<Instruction> instructions = treatment.immediate();
        final JsonNode jsonInstructions = jsonTreatment.get("instructions");
        if (jsonInstructions.size() != instructions.size()) {
            description.appendText("size of instructions array is "
                    + Integer.toString(jsonInstructions.size()));
            return false;
        }

        for (Instruction instruction : instructions) {
            boolean instructionFound = false;
            for (int instructionIndex = 0; instructionIndex < jsonInstructions.size(); instructionIndex++) {
                final InstructionJsonMatcher instructionMatcher =
                        InstructionJsonMatcher.matchesInstruction(instruction);
                if (instructionMatcher.matches(jsonInstructions.get(instructionIndex))) {
                    instructionFound = true;
                    break;
                }
            }
            if (!instructionFound) {
                description.appendText("instruction not found " + instruction.toString());
                return false;
            }
        }

        // Check constraints
        final JsonNode jsonConstraints = jsonIntent.get("constraints");
        if (connectivityIntent.constraints() != null) {
            if (connectivityIntent.constraints().size() != jsonConstraints.size()) {
                description.appendText("constraints array size was "
                        + Integer.toString(jsonConstraints.size()));
                return false;
            }
            for (final Constraint constraint : connectivityIntent.constraints()) {
                boolean constraintFound = false;
                for (int constraintIndex = 0; constraintIndex < jsonConstraints.size();
                     constraintIndex++) {
                    final JsonNode value = jsonConstraints.get(constraintIndex);
                    if (matchConstraint(constraint, value)) {
                        constraintFound = true;
                    }
                }
                if (!constraintFound) {
                    final String constraintString = constraint.toString();
                    description.appendText("constraint missing " + constraintString);
                    return false;
                }
            }
        } else if (jsonConstraints.size() != 0) {
            description.appendText("constraint array not empty");
            return false;
        }

        if (connectivityIntent instanceof HostToHostIntent) {
            return matchHostToHostIntent(jsonIntent, description);
        } else if (connectivityIntent instanceof PointToPointIntent) {
            return matchPointToPointIntent(jsonIntent, description);
        } else {
            description.appendText("class of connectivity intent is unknown");
            return false;
        }
    }

    @Override
    public boolean matchesSafely(JsonNode jsonIntent, Description description) {
        // check id
        final String jsonId = jsonIntent.get("id").asText();
        final String id = intent.id().toString();
        if (!jsonId.equals(id)) {
            description.appendText("id was " + jsonId);
            return false;
        }

        // check application id
        final JsonNode jsonAppIdNode = jsonIntent.get("appId");

        final String jsonAppId = jsonAppIdNode.asText();
        final String appId = intent.appId().name();
        if (!jsonAppId.equals(appId)) {
            description.appendText("appId was " + jsonAppId);
            return false;
        }

        // check intent type
        final String jsonType = jsonIntent.get("type").asText();
        final String type = intent.getClass().getSimpleName();
        if (!jsonType.equals(type)) {
            description.appendText("type was " + jsonType);
            return false;
        }

        // check resources array
        final JsonNode jsonResources = jsonIntent.get("resources");
        if (intent.resources() != null) {
            if (intent.resources().size() != jsonResources.size()) {
                description.appendText("resources array size was "
                                       + Integer.toString(jsonResources.size()));
                return false;
            }
            for (final NetworkResource resource : intent.resources()) {
                boolean resourceFound = false;
                final String resourceString = resource.toString();
                for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
                    final JsonNode value = jsonResources.get(resourceIndex);
                    if (value.asText().equals(resourceString)) {
                        resourceFound = true;
                    }
                }
                if (!resourceFound) {
                    description.appendText("resource missing " + resourceString);
                    return false;
                }
            }
        } else if (jsonResources.size() != 0) {
            description.appendText("resources array empty");
            return false;
        }

        if (intent instanceof ConnectivityIntent) {
            return matchConnectivityIntent(jsonIntent, description);
        } else {
            description.appendText("class of intent is unknown");
            return false;
        }
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(intent.toString());
    }

    /**
     * Factory to allocate an intent matcher.
     *
     * @param intent intent object we are looking for
     * @return matcher
     */
    public static IntentJsonMatcher matchesIntent(Intent intent) {
        return new IntentJsonMatcher(intent);
    }
}
