/*
 * Copyright 2017-present 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.drivers.huawei;

import org.onosproject.yang.gen.v1.l3vpn.comm.type.rev20141225.nel3vpncommtype.Ipv4Address;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.DeviceKeys;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.device.DefaultL3Vpn;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.device.l3vpn.DefaultL3Vpncomm;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.DefaultL3VpnInstances;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.DefaultL3VpnInstance;
import org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225.nel3vpnapi.devices.device.l3vpn.l3vpncomm.l3vpninstances.L3VpnInstanceKeys;
import org.onosproject.yang.gen.v1.ne.l3vpn.comm.rev20141225.nel3vpncomm.l3vpnifs.DefaultL3VpnIfs;
import org.onosproject.yang.gen.v1.ne.l3vpn.comm.rev20141225.nel3vpncomm.l3vpnifs.L3VpnIfs;
import org.onosproject.yang.gen.v1.ne.l3vpn.comm.rev20141225.nel3vpncomm.l3vpnifs.l3vpnifs.DefaultL3VpnIf;
import org.onosproject.yang.gen.v1.ne.l3vpn.comm.rev20141225.nel3vpncomm.l3vpnifs.l3vpnifs.L3VpnIf;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.DefaultDevices;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.Device;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.device.Interfaces;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.device.interfaces.DefaultYangAutoPrefixInterface;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev20140508.ietfinterfaces.devices.device.interfaces.YangAutoPrefixInterface;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev20140616.ietfip.devices.device.interfaces.yangautoprefixinterface.augmentedifinterface.Ipv4;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev20140616.ietfip.devices.device.interfaces.yangautoprefixinterface.augmentedifinterface.ipv4.Address;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev20140616.ietfip.devices.device.interfaces.yangautoprefixinterface.augmentedifinterface.ipv4.address.subnet.PrefixLength;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.instance.rev20160623.ietfnetworkinstance.devices.device.interfaces.yangautoprefixinterface.DefaultAugmentedIfInterface;
import org.onosproject.yang.model.InnerModelObject;
import org.onosproject.yang.model.ModelObjectData;
import org.onosproject.yang.model.ModelObjectId;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import static org.onosproject.drivers.huawei.DriverUtil.DEVICE_NULL;
import static org.onosproject.drivers.huawei.DriverUtil.OBJECT_NULL;
import static org.onosproject.drivers.huawei.DriverUtil.getData;
import static org.onosproject.drivers.huawei.DriverUtil.getIdFromModId;
import static org.onosproject.drivers.huawei.DriverUtil.getObjFromModData;
import static org.onosproject.yang.gen.v1.l3vpn.comm.type.rev20141225.nel3vpncommtype.Ipv4Address.fromString;

/**
 * Representation of utility for interface creation and deletion.
 */
public final class IntConstructionUtil {

    /**
     * Error message for illegal length of mask.
     */
    private static final String ILLEGAL_MASK_LENGTH = "Illegal length of mask" +
            " is not allowed.";

    // No instantiation.
    private IntConstructionUtil() {
    }

    /**
     * Returns the created model object data of VPN bounded interface of huawei
     * device from the standard model object data.
     *
     * @param modObj model object data
     * @return driver interface model object data
     */
    static ModelObjectData getCreateInt(ModelObjectData modObj) {
        boolean isModIdAvail = true;
        String id = getIdFromModId(modObj.identifier(), false);
        Object obj = getObjFromModData(modObj);
        if (id == null) {
            isModIdAvail = false;
            id = getIdFromRootObj(obj);
            obj = getObjFromDevObj(obj);
        }
        if (obj == null) {
            throw new IllegalArgumentException(OBJECT_NULL);
        }
        List<YangAutoPrefixInterface> intList = ((Interfaces) obj)
                .yangAutoPrefixInterface();
        YangAutoPrefixInterface l3Int = intList.get(0);
        DefaultAugmentedIfInterface ifInt =
                ((DefaultYangAutoPrefixInterface) l3Int).augmentation(
                        DefaultAugmentedIfInterface.class);
        String insName = ifInt.bindNetworkInstanceName();
        L3VpnIfs l3VpnIfs = getDriverInterfaces(l3Int);
        return getDriModObj(id, insName, l3VpnIfs, isModIdAvail);
    }

    /**
     * Returns the driver model object data, according to the levels it has
     * to be constructed.
     *
     * @param id           device id
     * @param insName      VPN name
     * @param l3VpnIfs     driver VPN if object
     * @param isModIdAvail model id availability
     * @return driver model object data
     */
    private static ModelObjectData getDriModObj(String id, String insName,
                                                L3VpnIfs l3VpnIfs,
                                                boolean isModIdAvail) {
        List<L3VpnIf> intList = l3VpnIfs.l3VpnIf();
        Iterator<L3VpnIf> it = intList.iterator();
        L3VpnIf l3VpnIf = it.next();
        ModelObjectData data;
        ModelObjectId.Builder objId = getModIdBuilder(id, insName);
        if (isModIdAvail) {
            objId.addChild(DefaultL3VpnIfs.class);
            data = getData(objId.build(), (InnerModelObject) l3VpnIf);
        } else {
            data = getData(objId.build(), (InnerModelObject) l3VpnIfs);
        }
        return data;
    }

    private static ModelObjectId.Builder getModIdBuilder(String id,
                                                         String vpnName) {
        DeviceKeys key = new DeviceKeys();
        key.deviceid(id);
        L3VpnInstanceKeys insKey = new L3VpnInstanceKeys();
        insKey.vrfName(vpnName);
        return ModelObjectId.builder()
                .addChild(org.onosproject.yang.gen.v1.ne.l3vpn.api.rev20141225
                                  .nel3vpnapi.DefaultDevices.class)
                .addChild(org.onosproject.yang.gen.v1.ne.l3vpn.api
                                  .rev20141225.nel3vpnapi.devices
                                  .DefaultDevice.class, key)
                .addChild(DefaultL3Vpn.class)
                .addChild(DefaultL3Vpncomm.class)
                .addChild(DefaultL3VpnInstances.class)
                .addChild(DefaultL3VpnInstance.class, insKey);
    }

    /**
     * Returns the driver interfaces from the standard device model interfaces.
     *
     * @param ifs standard device model interfaces
     * @return driver interfaces
     */
    private static L3VpnIfs getDriverInterfaces(YangAutoPrefixInterface ifs) {
        L3VpnIfs l3VpnIfs = new DefaultL3VpnIfs();
        L3VpnIf l3VpnIf = new DefaultL3VpnIf();
        List<L3VpnIf> l3VpnIfList = new LinkedList<>();
        l3VpnIf.ifName(ifs.name());
        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip
                .rev20140616.ietfip.devices.device.interfaces
                .yangautoprefixinterface.DefaultAugmentedIfInterface ipAug =
                ((DefaultYangAutoPrefixInterface) ifs).augmentation(
                        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang
                                .ietf.ip.rev20140616.ietfip.devices.device
                                .interfaces.yangautoprefixinterface
                                .DefaultAugmentedIfInterface.class);

        if (ipAug != null && ipAug.ipv4() != null) {
            Ipv4 ipAddress = ipAug.ipv4();
            for (Address add : ipAddress.address()) {
                Ipv4Address v4Add = fromString(add.ip().ipv4Address()
                                                       .toString());
                Ipv4Address subnet = fromString(getSubnet(
                        ((PrefixLength) add.subnet()).prefixLength()));
                l3VpnIf.ipv4Addr(v4Add);
                l3VpnIf.subnetMask(subnet);
            }
        }
        l3VpnIfList.add(l3VpnIf);
        l3VpnIfs.l3VpnIf(l3VpnIfList);
        return l3VpnIfs;
    }

    /**
     * Returns the device id from the root object.
     *
     * @param obj root object
     * @return device id
     */
    private static String getIdFromRootObj(Object obj) {
        Device dev = getDevFromRootObj(obj);
        return dev.deviceid();
    }

    /**
     * Returns the device from the root object.
     *
     * @param obj root object
     * @return device object
     */
    private static Device getDevFromRootObj(Object obj) {
        List<Device> deviceList = ((DefaultDevices) obj).device();
        Iterator<Device> it = deviceList.iterator();
        if (it.hasNext()) {
            return it.next();
        }
        throw new IllegalArgumentException(DEVICE_NULL);
    }

    /**
     * Returns the interfaces object from the root object.
     *
     * @param obj root object
     * @return interfaces object
     */
    private static Interfaces getObjFromDevObj(Object obj) {
        Device dev = getDevFromRootObj(obj);
        return dev.interfaces();
    }

    /**
     * Returns the subnet address from the mask value.
     *
     * @param mask mask value
     * @return subnet address
     */
    private static String getSubnet(short mask) {
        int value = 0xffffffff << (32 - mask);
        byte[] bytes = new byte[]{
                (byte) (value >>> 24), (byte) (value >> 16 & 0xff),
                (byte) (value >> 8 & 0xff), (byte) (value & 0xff)};
        InetAddress netAdd;
        try {
            netAdd = InetAddress.getByAddress(bytes);
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException(ILLEGAL_MASK_LENGTH);
        }
        return netAdd.getHostAddress();
    }
}
