/*
 * Copyright 2016 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.driver.extensions;

import org.onlab.packet.VlanId;
import org.onosproject.net.behaviour.ExtensionSelectorResolver;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType;
import org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes;
import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVidMasked;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.VlanVid;

/**
 * Interpreter for OFDPA OpenFlow selector extensions.
 */
public class OfdpaExtensionSelectorInterpreter extends AbstractHandlerBehaviour
        implements ExtensionSelectorInterpreter, ExtensionSelectorResolver {

    @Override
    public boolean supported(ExtensionSelectorType extensionSelectorType) {
        if (extensionSelectorType.equals(ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
            return true;
        }
        return false;
    }

    @Override
    public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) {
        ExtensionSelectorType type = extensionSelector.type();
        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
            VlanId vlanId = ((OfdpaMatchVlanVid) extensionSelector).vlanId();
            // Special VLAN 0x0000/0x1FFF required by OFDPA
            if (vlanId.equals(VlanId.NONE)) {
                OFVlanVidMatch vid = OFVlanVidMatch.ofRawVid((short) 0x0000);
                OFVlanVidMatch mask = OFVlanVidMatch.ofRawVid((short) 0x1FFF);
                return factory.oxms().vlanVidMasked(vid, mask);
            // Normal case
            } else if (vlanId.equals(VlanId.ANY)) {
                return factory.oxms().vlanVidMasked(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT);
            } else {
                return factory.oxms().vlanVid(OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vlanId.toShort())));
            }
        }
        throw new UnsupportedOperationException(
                "Unexpected ExtensionSelector: " + extensionSelector.toString());
    }

    @Override
    public ExtensionSelector mapOxm(OFOxm<?> oxm) {
        VlanId vlanId;

        if (oxm.getMatchField().equals(MatchField.VLAN_VID)) {
            if (oxm.isMasked()) {
                OFVlanVidMatch vid = ((OFOxmVlanVidMasked) oxm).getValue();
                OFVlanVidMatch mask = ((OFOxmVlanVidMasked) oxm).getMask();

                if (vid.equals(OFVlanVidMatch.ofRawVid((short) 0))) {
                    vlanId = VlanId.NONE;
                } else if (vid.equals(OFVlanVidMatch.PRESENT) &&
                        mask.equals(OFVlanVidMatch.PRESENT)) {
                    vlanId = VlanId.ANY;
                } else {
                    vlanId = VlanId.vlanId(vid.getVlan());
                }
            } else {
                OFVlanVidMatch vid = ((OFOxmVlanVid) oxm).getValue();

                if (!vid.isPresentBitSet()) {
                    vlanId = VlanId.NONE;
                } else {
                    vlanId = VlanId.vlanId(vid.getVlan());
                }
            }
            return new OfdpaMatchVlanVid(vlanId);
        }
        throw new UnsupportedOperationException(
                "Unexpected OXM: " + oxm.toString());
    }

    @Override
    public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
            return new OfdpaMatchVlanVid();
        }
        throw new UnsupportedOperationException(
                "Driver does not support extension type " + type.toString());
    }
}
