/*
 * 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.segmentrouting.web;

import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.segmentrouting.Policy;
import org.onosproject.segmentrouting.TunnelPolicy;

public final class PolicyCodec extends JsonCodec<Policy> {

    // JSON field names
    private static final String POLICY_ID = "policy_id";
    private static final String PRIORITY = "priority";
    private static final String TYPE = "policy_type";
    private static final String TUNNEL_ID = "tunnel_id";
    private static final String DST_IP = "dst_ip";
    private static final String SRC_IP = "src_ip";
    private static final String PROTO_TYPE = "proto_type";
    private static final String SRC_PORT = "src_tp_port";
    private static final String DST_PORT = "dst_tp_port";

    @Override
    public ObjectNode encode(Policy policy, CodecContext context) {
        final ObjectNode result = context.mapper().createObjectNode()
                .put(POLICY_ID, policy.id());

        result.put(PRIORITY, policy.priority());
        result.put(TYPE, policy.type().toString());

        if (policy.dstIp() != null) {
            result.put(DST_IP, policy.dstIp());
        }
        if (policy.srcIp() != null) {
            result.put(SRC_IP, policy.srcIp());
        }
        if (policy.ipProto() != null) {
            result.put(PROTO_TYPE, policy.ipProto());
        }

        int srcPort = policy.srcPort() & 0xffff;
        if (policy.srcPort() != 0) {
            result.put(SRC_PORT, srcPort);
        }
        int dstPort = policy.dstPort() & 0xffff;
        if (policy.dstPort() != 0) {
            result.put(DST_PORT, dstPort);
        }
        if (policy.type() == Policy.Type.TUNNEL_FLOW) {
            result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId());
        }

        return result;
    }

    @Override
    public Policy decode(ObjectNode json, CodecContext context) {

        String pid = json.path(POLICY_ID).asText();
        String type = json.path(TYPE).asText();
        int priority = json.path(PRIORITY).asInt();
        String dstIp = json.path(DST_IP).asText();
        String srcIp = json.path(SRC_IP).asText();
        String tunnelId = json.path(TUNNEL_ID).asText();
        String protoType = json.path(PROTO_TYPE).asText();
        short srcPort = json.path(SRC_PORT).shortValue();
        short dstPort = json.path(DST_PORT).shortValue();

        if (json.path(POLICY_ID).isMissingNode() || pid == null) {
            // TODO: handle errors
            return null;
        }

        TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid);
        if (!json.path(TYPE).isMissingNode() && type != null &&
                Policy.Type.valueOf(type).equals(Policy.Type.TUNNEL_FLOW)) {

            if (json.path(TUNNEL_ID).isMissingNode() || tunnelId == null) {
                return null;
            }

            tpb.setTunnelId(tunnelId);
            tpb.setType(Policy.Type.valueOf(type));

            if (!json.path(PRIORITY).isMissingNode()) {
                tpb.setPriority(priority);
            }
            if (dstIp != null) {
                tpb.setDstIp(dstIp);
            }
            if (srcIp != null) {
                tpb.setSrcIp(srcIp);
            }
            if (protoType != null) {
                tpb.setIpProto(protoType);
            }
            if (dstPort != 0) {
                tpb.setDstPort(dstPort);
            }
            if (srcPort != 0) {
                tpb.setSrcPort(srcPort);
            }
        }

        return tpb.build();
    }

}
