/*
 * 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 org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.OchSignal;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.node.ObjectNode;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Instruction codec.
 */
public final class InstructionCodec extends JsonCodec<Instruction> {

    protected static final Logger log = LoggerFactory.getLogger(InstructionCodec.class);

    /**
     * Encode an L0 modification instruction.
     *
     * @param result json node that the instruction attributes are added to
     * @param instruction The L0 instruction
     */
    private void encodeL0(ObjectNode result, L0ModificationInstruction instruction) {
        result.put("subtype", instruction.subtype().name());

        switch (instruction.subtype()) {
            case LAMBDA:
                final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction =
                        (L0ModificationInstruction.ModLambdaInstruction) instruction;
                result.put("lambda", modLambdaInstruction.lambda());
                break;

            case OCH:
                L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction =
                        (L0ModificationInstruction.ModOchSignalInstruction) instruction;
                OchSignal ochSignal = ochSignalInstruction.lambda();
                result.put("gridType", ochSignal.gridType().name());
                result.put("channelSpacing", ochSignal.channelSpacing().name());
                result.put("spacingMultiplier", ochSignal.spacingMultiplier());
                result.put("slotGranularity", ochSignal.slotGranularity());
                break;

            default:
                log.info("Cannot convert L0 subtype of {}", instruction.subtype());
        }
    }

    /**
     * Encode an L2 modification instruction.
     *
     * @param result json node that the instruction attributes are added to
     * @param instruction The L2 instruction
     * @param context context of the request
     */
    private void encodeL2(ObjectNode result,
                          L2ModificationInstruction instruction,
                          CodecContext context) {
        result.put("subtype", instruction.subtype().name());

        switch (instruction.subtype()) {
            case ETH_SRC:
            case ETH_DST:
                final L2ModificationInstruction.ModEtherInstruction modEtherInstruction =
                        (L2ModificationInstruction.ModEtherInstruction) instruction;
                result.put("mac", modEtherInstruction.mac().toString());
                break;

            case VLAN_ID:
                final L2ModificationInstruction.ModVlanIdInstruction modVlanIdInstruction =
                        (L2ModificationInstruction.ModVlanIdInstruction) instruction;
                result.put("vlanId", modVlanIdInstruction.vlanId().toShort());
                break;

            case VLAN_PCP:
                final L2ModificationInstruction.ModVlanPcpInstruction modVlanPcpInstruction =
                        (L2ModificationInstruction.ModVlanPcpInstruction) instruction;
                result.put("vlanPcp", modVlanPcpInstruction.vlanPcp());
                break;

            case MPLS_LABEL:
                final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
                        (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
                result.put("label", modMplsLabelInstruction.label());
                break;

            case MPLS_PUSH:
                final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) instruction;

                result.put("ethernetType", pushHeaderInstructions.ethernetType());
                break;

            default:
                log.info("Cannot convert L2 subtype of {}", instruction.subtype());
                break;
        }
    }

    /**
     * Encode an L3 modification instruction.
     *
     * @param result json node that the instruction attributes are added to
     * @param instruction The L3 instruction
     */
    private void encodeL3(ObjectNode result, L3ModificationInstruction instruction) {
        result.put("subtype", instruction.subtype().name());
        switch (instruction.subtype()) {
            case IPV4_SRC:
            case IPV4_DST:
            case IPV6_SRC:
            case IPV6_DST:
                final L3ModificationInstruction.ModIPInstruction modIPInstruction =
                        (L3ModificationInstruction.ModIPInstruction) instruction;
                result.put("ip", modIPInstruction.ip().toString());
                break;

            case IPV6_FLABEL:
                final L3ModificationInstruction.ModIPv6FlowLabelInstruction
                    modFlowLabelInstruction =
                        (L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
                result.put("flowLabel", modFlowLabelInstruction.flowLabel());
                break;

            default:
                log.info("Cannot convert L3 subtype of {}", instruction.subtype());
                break;
        }
    }

    @Override
    public ObjectNode encode(Instruction instruction, CodecContext context) {
        checkNotNull(instruction, "Instruction cannot be null");

        final ObjectNode result = context.mapper().createObjectNode()
                .put("type", instruction.type().toString());


        switch (instruction.type()) {
            case OUTPUT:
                final Instructions.OutputInstruction outputInstruction =
                        (Instructions.OutputInstruction) instruction;
                result.put("port", outputInstruction.port().toLong());
                break;

            case DROP:
                break;

            case L0MODIFICATION:
                final L0ModificationInstruction l0ModificationInstruction =
                        (L0ModificationInstruction) instruction;
                encodeL0(result, l0ModificationInstruction);
                break;

            case L2MODIFICATION:
                final L2ModificationInstruction l2ModificationInstruction =
                        (L2ModificationInstruction) instruction;
                encodeL2(result, l2ModificationInstruction, context);
                break;

            case L3MODIFICATION:
                final L3ModificationInstruction l3ModificationInstruction =
                        (L3ModificationInstruction) instruction;
                encodeL3(result, l3ModificationInstruction);
                break;

            default:
                log.info("Cannot convert instruction type of {}", instruction.type());
                break;
        }
        return result;
    }
}
