/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.openstacktelemetry.codec;

import com.fasterxml.jackson.databind.JsonNode;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.onosproject.openstacktelemetry.api.FlowInfo;
import org.onosproject.openstacktelemetry.api.StatsInfo;

/**
 * Hamcrest matcher for flow info.
 */
public final class FlowInfoJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {

    private final FlowInfo flowInfo;

    private static final String FLOW_TYPE = "flowType";
    private static final String DEVICE_ID = "deviceId";
    private static final String INPUT_INTERFACE_ID = "inputInterfaceId";
    private static final String OUTPUT_INTERFACE_ID = "outputInterfaceId";

    private static final String VLAN_ID = "vlanId";
    private static final String VXLAN_ID = "vxlanId";
    private static final String SRC_IP = "srcIp";
    private static final String SRC_IP_PREFIX_LEN = "srcIpPrefixLength";
    private static final String DST_IP = "dstIp";
    private static final String DST_IP_PREFIX_LEN = "dstIpPrefixLength";
    private static final String SRC_PORT = "srcPort";
    private static final String DST_PORT = "dstPort";
    private static final String PROTOCOL = "protocol";
    private static final String SRC_MAC = "srcMac";
    private static final String DST_MAC = "dstMac";
    private static final String STATS_INFO = "statsInfo";

    private FlowInfoJsonMatcher(FlowInfo flowInfo) {
        this.flowInfo = flowInfo;
    }

    @Override
    protected boolean matchesSafely(JsonNode jsonNode, Description description) {

        // check flow type
        String jsonFlowType = jsonNode.get(FLOW_TYPE).asText();
        String flowType = String.valueOf(flowInfo.flowType());
        if (!jsonFlowType.equals(flowType)) {
            description.appendText("flow type was " + jsonFlowType);
            return false;
        }

        // check device id
        String jsonDeviceId = jsonNode.get(DEVICE_ID).asText();
        String deviceId = flowInfo.deviceId().toString();
        if (!jsonDeviceId.equals(deviceId)) {
            description.appendText("device id was " + jsonDeviceId);
            return false;
        }

        // check input interface id
        int jsonInputInterfaceId = jsonNode.get(INPUT_INTERFACE_ID).asInt();
        int inputInterfaceId = flowInfo.inputInterfaceId();
        if (jsonInputInterfaceId != inputInterfaceId) {
            description.appendText("input interface id was " + jsonInputInterfaceId);
            return false;
        }

        // check output interface id
        int jsonOutputInterfaceId = jsonNode.get(OUTPUT_INTERFACE_ID).asInt();
        int outputInterfaceId = flowInfo.outputInterfaceId();
        if (jsonOutputInterfaceId != outputInterfaceId) {
            description.appendText("output interface id was " + jsonInputInterfaceId);
            return false;
        }

        // check vlan id
        String jsonVlanId = jsonNode.get(VLAN_ID).asText();
        String vlanId = flowInfo.vlanId().toString();
        if (!jsonVlanId.equals(vlanId)) {
            description.appendText("VLAN id was " + jsonVlanId);
            return false;
        }

        // check source IP
        String jsonSrcIp = jsonNode.get(SRC_IP).asText();
        String srcIp = flowInfo.srcIp().address().toString();
        if (!jsonSrcIp.equals(srcIp)) {
            description.appendText("Source IP was " + jsonSrcIp);
            return false;
        }

        // check destination IP
        String jsonDstIp = jsonNode.get(DST_IP).asText();
        String dstIp = flowInfo.dstIp().address().toString();
        if (!jsonDstIp.equals(dstIp)) {
            description.appendText("Destination IP was " + jsonDstIp);
            return false;
        }

        // check source IP prefix length
        int jsonSrcPrefixLength = jsonNode.get(SRC_IP_PREFIX_LEN).asInt();
        int srcPrefixLength = flowInfo.srcIp().prefixLength();
        if (jsonSrcPrefixLength != srcPrefixLength) {
            description.appendText("Source IP prefix length was " + jsonSrcPrefixLength);
            return false;
        }

        // check destination IP prefix length
        int jsonDstPrefixLength = jsonNode.get(DST_IP_PREFIX_LEN).asInt();
        int dstPrefixLength = flowInfo.dstIp().prefixLength();
        if (jsonDstPrefixLength != dstPrefixLength) {
            description.appendText("Destination IP prefix length was " + jsonDstPrefixLength);
            return false;
        }

        // check source port
        int jsonSrcPort = jsonNode.get(SRC_PORT).asInt();
        int srcPort = flowInfo.srcPort().toInt();
        if (jsonSrcPort != srcPort) {
            description.appendText("Source port was " + jsonSrcPort);
            return false;
        }

        // check destination port
        int jsonDstPort = jsonNode.get(DST_PORT).asInt();
        int dstPort = flowInfo.dstPort().toInt();
        if (jsonDstPort != dstPort) {
            description.appendText("Destination port was " + jsonDstPort);
            return false;
        }

        // check protocol
        String jsonProtocol = jsonNode.get(PROTOCOL).asText();
        String protocol = String.valueOf(flowInfo.protocol());
        if (!jsonProtocol.equals(protocol)) {
            description.appendText("Protocol was " + jsonProtocol);
            return false;
        }

        // check source mac
        String jsonSrcMac = jsonNode.get(SRC_MAC).asText();
        String srcMac = flowInfo.srcMac().toString();
        if (!jsonSrcMac.equals(srcMac)) {
            description.appendText("Source MAC was " + jsonSrcMac);
            return false;
        }

        // check destination mac
        String jsonDstMac = jsonNode.get(DST_MAC).asText();
        String dstMac = flowInfo.dstMac().toString();
        if (!jsonDstMac.equals(dstMac)) {
            description.appendText("Destination MAC was " + jsonDstMac);
            return false;
        }

        // check stats info
        JsonNode jsonStatsInfo = jsonNode.get(STATS_INFO);
        if (jsonStatsInfo != null) {
            StatsInfo statsInfo = flowInfo.statsInfo();
            StatsInfoJsonMatcher infoMatcher =
                    StatsInfoJsonMatcher.matchStatsInfo(statsInfo);
            return infoMatcher.matches(jsonStatsInfo);
        }

        return true;
    }

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

    /**
     * Factory to allocate an flow info matcher.
     *
     * @param flowInfo flow info object we are looking for
     * @return matcher
     */
    public static FlowInfoJsonMatcher matchesFlowInfo(FlowInfo flowInfo) {
        return new FlowInfoJsonMatcher(flowInfo);
    }
}
