/* Copyright 2017 Telstra Open Source
 *
 *   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.openkilda.messaging.info.event;

import static com.google.common.base.MoreObjects.toStringHelper;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.Serializable;
import java.util.Objects;

/**
 * Defines the payload payload of a Message representing a path node info.
 */
@JsonSerialize
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "switch_id",
        "port_no",
        "seq_id",
        "segment_latency"})
public class PathNode implements Serializable {
    /**
     * Serialization version number constant.
     */
    private static final long serialVersionUID = 1L;

    /**
     * Switch id.
     */
    @JsonProperty("switch_id")
    private String switchId;

    /**
     * Port number.
     */
    @JsonProperty("port_no")
    private int portNo;

    /**
     * Sequence id.
     */
    @JsonProperty("seq_id")
    private int seqId;

    /**
     * Segment latency.
     */
    @JsonInclude(JsonInclude.Include.NON_DEFAULT) // Needed to exclude when not set
    @JsonProperty("segment_latency")
    private Long segmentLatency;

    /**
     * Default constructor.
     */
    public PathNode() {
    }

    /**
     * Copy constructor.
     *
     * @param that {@link PathNode} instance
     */
    public PathNode(PathNode that) {
        this.seqId = that.seqId;
        this.portNo = that.portNo;
        this.switchId = that.switchId;
        this.segmentLatency = that.segmentLatency;
    }

    /**
     * Instance creator without segment latency value.
     *
     * @param switchId switch id
     * @param portNo   port number
     * @param seqId    sequence id
     */
    public PathNode(final String switchId, final int portNo, final int seqId) {
        this.switchId = switchId;
        this.portNo = portNo;
        this.seqId = seqId;
    }

    /**
     * Instance creator.
     *
     * @param switchId       switch id
     * @param portNo         port number
     * @param seqId          sequence id
     * @param segmentLatency segment latency
     */
    @JsonCreator
    public PathNode(@JsonProperty("switch_id") final String switchId,
                    @JsonProperty("port_no") final int portNo,
                    @JsonProperty("seq_id") final int seqId,
                    @JsonProperty("segment_latency") final Long segmentLatency) {
        this.switchId = switchId;
        this.portNo = portNo;
        this.seqId = seqId;
        this.segmentLatency = segmentLatency;
    }

    /**
     * Returns switch id.
     *
     * @return switch id
     */
    @JsonProperty("switch_id")
    public String getSwitchId() {
        return switchId;
    }

    /**
     * Sets switch id.
     *
     * @param switchId switch id to set
     */
    @JsonProperty("switch_id")
    public void setSwitchId(final String switchId) {
        this.switchId = switchId;
    }

    /**
     * Returns port number.
     *
     * @return port number
     */
    @JsonProperty("port_no")
    public int getPortNo() {
        return portNo;
    }

    /**
     * Sets port number.
     *
     * @param portNo port number to set
     */
    @JsonProperty("port_no")
    public void setPortNo(final int portNo) {
        this.portNo = portNo;
    }

    /**
     * Returns sequence id.
     *
     * @return sequence id
     */
    @JsonProperty("seq_id")
    public int getSeqId() {
        return seqId;
    }

    /**
     * Sets sequence id.
     *
     * @param seqId sequence id to set
     */
    @JsonProperty("seq_id")
    public void setSeqId(final int seqId) {
        this.seqId = seqId;
    }

    /**
     * Returns segment latency.
     *
     * @return segment latency
     */
    @JsonProperty("segment_latency")
    public Long getSegLatency() {
        return segmentLatency;
    }

    /**
     * Sets segment latency.
     *
     * @param latency segment latency to set
     */
    @JsonProperty("segment_latency")
    public void setSegLatency(final long latency) {
        this.segmentLatency = latency;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return toStringHelper(this)
                .add("switch_id", switchId)
                .add("port_no", portNo)
                .add("seq_id", seqId)
                .add("segment_latency", segmentLatency)
                .toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return Objects.hash(switchId, portNo);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object == null || getClass() != object.getClass()) {
            return false;
        }

        PathNode that = (PathNode) object;
        return Objects.equals(getSwitchId(), that.getSwitchId())
                && Objects.equals(getPortNo(), that.getPortNo());
    }
}

@@ -1943,16 +1943,209 @@
 tency;%0A%0A
+    /**%0A     * If a per segment cookie is set.%0A     */%0A    @JsonInclude(JsonInclude.Include.NON_DEFAULT) // Needed to exclude when not set%0A    @JsonProperty(%22cookie%22)%0A    private Long cookie;%0A%0A
     /**%0A
@@ -2168,24 +2168,24 @@
 onstructor.%0A
-
      */%0A    
@@ -2491,32 +2491,67 @@
 segmentLatency;%0A
+        this.cookie = that.cookie;%0A
     %7D%0A%0A    /**%0A 
@@ -3322,24 +3322,87 @@
  int seqId,%0A
+                    @JsonProperty(%22cookie%22) final Long cookie,%0A
             
@@ -3559,24 +3559,53 @@
 Id = seqId;%0A
+        this.cookie = cookie%0A
         this
@@ -5123,32 +5123,32 @@
 long latency) %7B%0A
-
         this.seg
@@ -5169,32 +5169,227 @@
 latency;%0A    %7D%0A%0A
+%0A    @JsonProperty(%22cookie%22)%0A    public Long getCookie() %7B%0A        return cookie;%0A    %7D%0A%0A    @JsonProperty(%22cookie%22)%0A    public void setCookie(Long cookie) %7B%0A        this.cookie = cookie;%0A    %7D%0A%0A
     /**%0A     * %7B

Add optional 'cookie' to PathNode