/*
 * Copyright 2014 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.net.flow.instructions;

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

import java.util.Objects;

import org.onlab.packet.IpAddress;

/**
 * Abstraction of a single traffic treatment step.
 */
public abstract class L3ModificationInstruction implements Instruction {

    /**
     * Represents the type of traffic treatment.
     */
    public enum L3SubType {
        /**
         * IPv4 src modification.
         */
        IPV4_SRC,

        /**
         * IPv4 dst modification.
         */
        IPV4_DST,

        /**
         * IPv6 src modification.
         */
        IPV6_SRC,

        /**
         * IPv6 dst modification.
         */
        IPV6_DST,

        /**
         * IPv6 flow label modification.
         */
        IPV6_FLABEL,

        /**
         * Decrement TTL.
         */
        DEC_TTL,

        /**
         * Copy TTL out.
         */
        TTL_OUT,

        /**
         * Copy TTL in.
         */
        TTL_IN

        //TODO: remaining types
    }

    /**
     * Returns the subtype of the modification instruction.
     * @return type of instruction
     */
    public abstract L3SubType subtype();

    @Override
    public Type type() {
        return Type.L3MODIFICATION;
    }

    /**
     * Represents a L3 src/dst modification instruction.
     */
    public static final class ModIPInstruction extends L3ModificationInstruction {

        private final L3SubType subtype;
        private final IpAddress ip;

        public ModIPInstruction(L3SubType subType, IpAddress addr) {

            this.subtype = subType;
            this.ip = addr;
        }

        @Override
        public L3SubType subtype() {
            return this.subtype;
        }

        public IpAddress ip() {
            return this.ip;
        }

        @Override
        public String toString() {
            return toStringHelper(subtype().toString())
                    .add("ip", ip).toString();
        }

        @Override
        public int hashCode() {
            return Objects.hash(type(), subtype(), ip);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof ModIPInstruction) {
                ModIPInstruction that = (ModIPInstruction) obj;
                return  Objects.equals(ip, that.ip) &&
                        Objects.equals(this.type(), that.type()) &&
                        Objects.equals(this.subtype(), that.subtype());

            }
            return false;
        }
    }

    /**
     * Represents a L3 IPv6 Flow Label (RFC 6437) modification instruction
     * (20 bits unsigned integer).
     */
    public static final class ModIPv6FlowLabelInstruction
        extends L3ModificationInstruction {
        private static final int MASK = 0xfffff;
        private final int flowLabel;            // IPv6 flow label: 20 bits

        /**
         * Constructor.
         *
         * flowLabel the IPv6 flow label to set in the treatment (20 bits)
         */
        public ModIPv6FlowLabelInstruction(int flowLabel) {
            this.flowLabel = flowLabel & MASK;
        }

        @Override
        public L3SubType subtype() {
            return L3SubType.IPV6_FLABEL;
        }

        /**
         * Gets the IPv6 flow label to set in the treatment.
         *
         * @return the IPv6 flow label to set in the treatment (20 bits)
         */
        public int flowLabel() {
            return this.flowLabel;
        }

        @Override
        public String toString() {
            return toStringHelper(subtype().toString())
                .add("flowLabel", Long.toHexString(flowLabel)).toString();
        }

        @Override
        public int hashCode() {
            return Objects.hash(type(), subtype(), flowLabel);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof ModIPv6FlowLabelInstruction) {
                ModIPv6FlowLabelInstruction that =
                    (ModIPv6FlowLabelInstruction) obj;
                return  Objects.equals(flowLabel, that.flowLabel) &&
                        Objects.equals(this.type(), that.type()) &&
                        Objects.equals(this.subtype(), that.subtype());
            }
            return false;
        }
    }

    /**
     * Represents a L3 TTL modification instruction.
     */
    public static final class ModTtlInstruction extends L3ModificationInstruction {

        private final L3SubType subtype;

        public ModTtlInstruction(L3SubType subtype) {
            this.subtype = subtype;
        }

        @Override
        public L3SubType subtype() {
            return this.subtype;
        }

        @Override
        public String toString() {
            return toStringHelper(subtype().toString())
                    .toString();
        }

        @Override
        public int hashCode() {
            return Objects.hash(type(), subtype());
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof ModTtlInstruction) {
                ModTtlInstruction that = (ModTtlInstruction) obj;
                return  Objects.equals(this.subtype(), that.subtype()) &&
                        Objects.equals(this.type(), that.type());

            }
            return false;
        }
    }
}
