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