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