/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.ospf.controller.impl;

import com.fasterxml.jackson.databind.JsonNode;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfProcess;
import org.onosproject.ospf.controller.area.OspfAreaImpl;
import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
import org.onosproject.ospf.controller.area.OspfProcessImpl;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * Representation of OSPF network configuration parsing util.
 */
public final class OspfConfigUtil {
    public static final String PROCESSID = "processId";
    public static final String AREAS = "areas";
    public static final String INTERFACEINDEX = "interfaceIndex";
    public static final String AREAID = "areaId";
    public static final String ROUTERID = "routerId";
    public static final String INTERFACE = "interface";
    public static final String HELLOINTERVAL = "helloIntervalTime";
    public static final String ROUTERDEADINTERVAL = "routerDeadIntervalTime";
    public static final String INTERFACETYPE = "interfaceType";
    public static final String EXTERNALROUTINGCAPABILITY = "externalRoutingCapability";
    private static final Logger log = LoggerFactory.getLogger(OspfConfigUtil.class);
    private static final String ISOPAQUE = "isOpaqueEnable";

    /**
     * Creates an instance of this.
     */
    private OspfConfigUtil() {

    }

    /**
     * Returns list of OSPF process from the json nodes.
     *
     * @param jsonNodes represents one or more OSPF process configuration
     * @return list of OSPF processes.
     */
    public static List<OspfProcess> processes(JsonNode jsonNodes) {
        List<OspfProcess> ospfProcesses = new ArrayList<>();
        if (jsonNodes == null) {
            return ospfProcesses;
        }
        //From each Process nodes, get area and related interface details.
        jsonNodes.forEach(jsonNode -> {
            List<OspfArea> areas = new ArrayList<>();
            //Get configured areas for the process.
            for (JsonNode areaNode : jsonNode.path(AREAS)) {
                List<OspfInterface> interfaceList = new ArrayList<>();
                for (JsonNode interfaceNode : areaNode.path(INTERFACE)) {
                    OspfInterface ospfInterface = interfaceDetails(interfaceNode);
                    if (ospfInterface != null) {
                        interfaceList.add(ospfInterface);
                    }
                }
                //Get the area details
                OspfArea area = areaDetails(areaNode);
                if (area != null) {
                    area.setOspfInterfaceList(interfaceList);
                    areas.add(area);
                }
            }
            OspfProcess process = new OspfProcessImpl();
            process.setProcessId(jsonNode.path(PROCESSID).asText());
            process.setAreas(areas);
            ospfProcesses.add(process);
        });

        return ospfProcesses;
    }

    /**
     * Returns interface IP by index.
     *
     * @param interfaceIndex interface index
     * @return interface IP by index
     */
    private static Ip4Address getInterfaceIp(int interfaceIndex) {
        Ip4Address ipAddress = null;
        try {
            NetworkInterface networkInterface = NetworkInterface.getByIndex(interfaceIndex);
            Enumeration ipAddresses = networkInterface.getInetAddresses();
            while (ipAddresses.hasMoreElements()) {
                InetAddress address = (InetAddress) ipAddresses.nextElement();
                if (!address.isLinkLocalAddress()) {
                    ipAddress = Ip4Address.valueOf(address.getAddress());
                    break;
                }
            }
        } catch (Exception e) {
            log.debug("Error while getting Interface IP by index");
            return OspfUtil.DEFAULTIP;
        }
        return ipAddress;
    }

    /**
     * Returns interface MAC by index.
     *
     * @param interfaceIndex interface index
     * @return interface IP by index
     */
    private static String getInterfaceMask(int interfaceIndex) {
        String subnetMask = null;
        try {
            Ip4Address ipAddress = getInterfaceIp(interfaceIndex);
            NetworkInterface networkInterface = NetworkInterface.getByInetAddress(
                    InetAddress.getByName(ipAddress.toString()));
            Enumeration ipAddresses = networkInterface.getInetAddresses();
            int index = 0;
            while (ipAddresses.hasMoreElements()) {
                InetAddress address = (InetAddress) ipAddresses.nextElement();
                if (!address.isLinkLocalAddress()) {
                    break;
                }
                index++;
            }
            int prfLen = networkInterface.getInterfaceAddresses().get(index).getNetworkPrefixLength();
            int shft = 0xffffffff << (32 - prfLen);
            int oct1 = ((byte) ((shft & 0xff000000) >> 24)) & 0xff;
            int oct2 = ((byte) ((shft & 0x00ff0000) >> 16)) & 0xff;
            int oct3 = ((byte) ((shft & 0x0000ff00) >> 8)) & 0xff;
            int oct4 = ((byte) (shft & 0x000000ff)) & 0xff;
            subnetMask = oct1 + "." + oct2 + "." + oct3 + "." + oct4;
        } catch (Exception e) {
            log.debug("Error while getting Interface network mask by index");
            return subnetMask;
        }
        return subnetMask;
    }

    /**
     * Checks if valid digit or not.
     *
     * @param strInput input value
     * @return true if valid else false
     */
    private static boolean isValidDigit(String strInput) {
        boolean isValid = true;
        if (isPrimitive(strInput)) {
            int input = Integer.parseInt(strInput);
            if (input < 1 || input > 255) {
                log.debug("Wrong config input value: {}", strInput);
                isValid = false;
            } else {
                isValid = true;
            }

        } else {
            isValid = false;
        }

        return isValid;
    }

    /**
     * Checks if primitive or not.
     *
     * @param value input value
     * @return true if number else false
     */
    private static boolean isPrimitive(String value) {
        boolean status = true;
        value = value.trim();
        if (value.length() < 1) {
            return false;
        }
        for (int i = 0; i < value.length(); i++) {
            char c = value.charAt(i);
            if (!Character.isDigit(c)) {
                status = false;
                break;
            }
        }

        return status;
    }

    /**
     * Checks if boolean or not.
     *
     * @param value input value
     * @return true if boolean else false
     */
    private static boolean isBoolean(String value) {
        boolean status = false;
        value = value.trim();
        if (value.equals("true") || value.equals("false")) {
            return true;
        }

        return status;
    }

    /**
     * Checks if given id is valid or not.
     *
     * @param value input value
     * @return true if valid else false
     */
    private static boolean isValidIpAddress(String value) {
        boolean status = true;
        try {
            Ip4Address ipAddress = Ip4Address.valueOf(value);
        } catch (Exception e) {
            log.debug("Invalid IP address string: {}", value);
            return false;
        }

        return status;
    }

    /**
     * Returns OSPF area instance from configuration.
     *
     * @param areaNode area configuration
     * @return OSPF area instance
     */
    private static OspfArea areaDetails(JsonNode areaNode) {
        OspfArea area = new OspfAreaImpl();
        String areaId = areaNode.path(AREAID).asText();
        if (isValidIpAddress(areaId)) {
            area.setAreaId(Ip4Address.valueOf(areaId));
        } else {
            log.debug("Wrong areaId: {}", areaId);
            return null;
        }
        String routerId = areaNode.path(ROUTERID).asText();
        if (isValidIpAddress(routerId)) {
            area.setRouterId(Ip4Address.valueOf(routerId));
        } else {
            log.debug("Wrong routerId: {}", routerId);
            return null;
        }
        String routingCapability = areaNode.path(EXTERNALROUTINGCAPABILITY).asText();
        if (isBoolean(routingCapability)) {
            area.setExternalRoutingCapability(Boolean.valueOf(routingCapability));
        } else {
            log.debug("Wrong routingCapability: {}", routingCapability);
            return null;
        }
        String isOpaqueEnabled = areaNode.path(ISOPAQUE).asText();
        if (isBoolean(isOpaqueEnabled)) {
            area.setIsOpaqueEnabled(Boolean.valueOf(isOpaqueEnabled));
        } else {
            log.debug("Wrong isOpaqueEnabled: {}", isOpaqueEnabled);
            return null;
        }
        area.setOptions(OspfUtil.HELLO_PACKET_OPTIONS);

        return area;
    }

    /**
     * Returns OSPF interface instance from configuration.
     *
     * @param interfaceNode interface configuration
     * @return OSPF interface instance
     */
    private static OspfInterface interfaceDetails(JsonNode interfaceNode) {
        OspfInterface ospfInterface = new OspfInterfaceImpl();
        String index = interfaceNode.path(INTERFACEINDEX).asText();
        if (isValidDigit(index)) {
            ospfInterface.setInterfaceIndex(Integer.parseInt(index));
        } else {
            log.debug("Wrong interface index: {}", index);
            return null;
        }
        Ip4Address interfaceIp = getInterfaceIp(ospfInterface.interfaceIndex());
        if (interfaceIp.equals(OspfUtil.DEFAULTIP)) {
            return null;
        }
        ospfInterface.setIpAddress(interfaceIp);
        ospfInterface.setIpNetworkMask(Ip4Address.valueOf(getInterfaceMask(
                ospfInterface.interfaceIndex())));
        ospfInterface.setBdr(OspfUtil.DEFAULTIP);
        ospfInterface.setDr(OspfUtil.DEFAULTIP);
        String helloInterval = interfaceNode.path(HELLOINTERVAL).asText();
        if (isValidDigit(helloInterval)) {
            ospfInterface.setHelloIntervalTime(Integer.parseInt(helloInterval));
        } else {
            log.debug("Wrong hello interval: {}", helloInterval);
            return null;
        }
        String routerDeadInterval = interfaceNode.path(ROUTERDEADINTERVAL).asText();
        if (isValidDigit(routerDeadInterval)) {
            ospfInterface.setRouterDeadIntervalTime(Integer.parseInt(routerDeadInterval));
        } else {
            log.debug("Wrong routerDeadInterval: {}", routerDeadInterval);
            return null;
        }
        String interfaceType = interfaceNode.path(INTERFACETYPE).asText();
        if (isValidDigit(interfaceType)) {
            ospfInterface.setInterfaceType(Integer.parseInt(interfaceType));
        } else {
            log.debug("Wrong interfaceType: {}", interfaceType);
            return null;
        }
        ospfInterface.setReTransmitInterval(OspfUtil.RETRANSMITINTERVAL);
        ospfInterface.setMtu(OspfUtil.MTU);
        ospfInterface.setRouterPriority(OspfUtil.ROUTER_PRIORITY);

        return ospfInterface;
    }
}
