/*
 * 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.netconf.client.impl;

import com.google.common.annotations.Beta;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.config.DynamicConfigEvent;
import org.onosproject.config.DynamicConfigListener;
import org.onosproject.config.DynamicConfigService;
import org.onosproject.config.ResourceIdParser;
import org.onosproject.config.Filter;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.DeviceId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.client.NetconfTranslator;
import org.onosproject.netconf.client.NetconfTranslator.OperationType;
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.InnerNode;
import org.onosproject.yang.model.LeafNode;
import org.onosproject.yang.model.ListKey;
import org.onosproject.yang.model.NodeKey;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.yang.runtime.DefaultResourceData;
import org.onlab.util.AbstractAccumulator;
import org.onlab.util.Accumulator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;

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


@Beta
@Component(immediate = true)
public class NetconfActiveComponent implements DynamicConfigListener {

    private static final Logger log = LoggerFactory.getLogger(NetconfActiveComponent.class);
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DynamicConfigService cfgService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetconfTranslator netconfTranslator;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetconfController controller;

    private final Accumulator<DynamicConfigEvent> accumulator = new InternalEventAccummulator();
    private static final String DEVNMSPACE = "ne-l3vpn-api";
    private static final String DEVICES = "devices";
    private static final String DEVICE = "device";
    private static final String DEVICE_ID = "deviceid";

    //Symbolic constants for use with the accumulator
    private static final int MAX_EVENTS = 1000;
    private static final int MAX_BATCH_MS = 5000;
    private static final int MAX_IDLE_MS = 1000;

    private ResourceId defParent = new ResourceId.Builder()
            .addBranchPointSchema(DEVICES, DEVNMSPACE)
            .addBranchPointSchema(DEVICE, DEVNMSPACE)
            .addBranchPointSchema(DEVICE_ID, DEVNMSPACE)
            .build();

    //TODO remove this hack after store ordering is fixed
    private static final String EXCPATH = "root|devices#ne-l3vpn-api|" +
            "device#ne-l3vpn-api$deviceid#ne-l3vpn-api#netconf:172.16.5.11:22|" +
            "l3vpn#ne-l3vpn-api|l3vpncomm#ne-l3vpn-api|l3vpnInstances#ne-l3vpn-api|" +
            "l3vpnInstance#ne-l3vpn-api$vrfName#ne-l3vpn-api#vrf2|l3vpnIfs#ne-l3vpn-api";
    //end of hack

    @Activate
    protected void activate() {
        cfgService.addListener(this);
        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        cfgService.removeListener(this);
        log.info("Stopped");
    }

    @Override
    public boolean isRelevant(DynamicConfigEvent event) {
        String resId = ResourceIdParser.parseResId(event.subject());
        String refId = ResourceIdParser.parseResId(defParent);
        return (resId.substring(0, (refId.length() - 1)).compareTo(refId) == 0);
    }

    public boolean isMaster(DeviceId deviceId) {
        return mastershipService.isLocalMaster(deviceId);
    }


    @Override
    public void event(DynamicConfigEvent event) {
        accumulator.add(event);
    }

    /**
     * Performs the delete operation corresponding to the passed event.
     *
     * @param node       a relevant dataNode
     * @param deviceId   the deviceId of the device to be updated
     * @param resourceId the resourceId of the root of the subtree to be edited
     * @return true if the update succeeds false otherwise
     */
    private boolean    configDelete(DataNode node, DeviceId deviceId, ResourceId resourceId) {
        return parseAndEdit(node, deviceId, resourceId, OperationType.DELETE);
    }

    /**
     * Performs the update operation corresponding to the passed event.
     *
     * @param node       a relevant dataNode
     * @param deviceId   the deviceId of the device to be updated
     * @param resourceId the resourceId of the root of the subtree to be edited
     * @return true if the update succeeds false otherwise
     */
    private boolean configUpdate(DataNode node, DeviceId deviceId, ResourceId resourceId) {
        return parseAndEdit(node, deviceId, resourceId, OperationType.REPLACE);
    }

    /**
     * Parses the incoming event and pushes configuration to the effected
     * device.
     *
     * @param node          the dataNode effecting a particular device of which this node
     *                      is master
     * @param deviceId      the deviceId of the device to be modified
     * @param resourceId    the resourceId of the root of the subtree to be edited
     * @param operationType the type of editing to be performed
     * @return true if the operation succeeds, false otherwise
     */
    private boolean parseAndEdit(DataNode node, DeviceId deviceId,
                                 ResourceId resourceId,
                                 NetconfTranslator.OperationType operationType) {
        //FIXME separate edit and delete, delete can proceed with a null node
        DefaultResourceData.Builder builder = DefaultResourceData.builder();
        if (node != null) {
            //add all low level nodes of devices
            Iterator<Map.Entry<NodeKey, DataNode>> it = ((InnerNode) node)
                    .childNodes().entrySet().iterator();
            while (it.hasNext()) {
                DataNode n = it.next().getValue();
                if (!n.key().schemaId().name().equals("deviceid")) {
                    builder.addDataNode(n);
                }
            }
        }
        //add resouce id //TODO: check if it is correct
        try {
            return netconfTranslator.editDeviceConfig(
                    deviceId, builder.build(), operationType);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Retrieves device id from Data node.
     *
     * @param node the node associated with the event
     * @return the deviceId of the effected device
     */
    @Beta
    public DeviceId getDeviceId(DataNode node) {
        String[] temp;
        String ip, port;
        if (node.type() == DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE) {
            temp = ((LeafNode) node).asString().split("\\:");
            if (temp.length != 3) {
                throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
            }
            ip = temp[1];
            port = temp[2];
        } else if (node.type() == DataNode.Type.MULTI_INSTANCE_NODE) {
            ListKey key = (ListKey) node.key();
            temp = key.keyLeafs().get(0).leafValAsString().split("\\:");
            if (temp.length != 3) {
                throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
            }
            ip = temp[1];
            port = temp[2];
        } else {
            throw new RuntimeException(new NetconfException("Invalid device id type, cannot apply"));
        }
        try {
            return DeviceId.deviceId(new URI("netconf", ip + ":" + port, (String) null));
        } catch (URISyntaxException var4) {
            throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, var4);
        }
    }

    /**
     * Inititates a Netconf connection to the device.
     *
     * @param deviceId of the added device
     */
    private void initiateConnection(DeviceId deviceId) {
        if (controller.getNetconfDevice(deviceId) == null) {
            try {
                //if (this.isReachable(deviceId)) {
                this.controller.connectDevice(deviceId);
                //}
            } catch (Exception ex) {
                throw new RuntimeException(new NetconfException("Unable to connect to NETCONF device on " +
                        deviceId, ex));
            }
        }
    }

    /**
     * Retrieves device key from Resource id.
     *
     * @param path associated with the event
     * @return the deviceId of the effected device
     */
    @Beta
    public ResourceId getDeviceKey(ResourceId path) {
        String resId = ResourceIdParser.parseResId(path);
        String[] el = resId.split(ResourceIdParser.EL_CHK);
        if (el.length < 2) {
            throw new RuntimeException(new NetconfException("Invalid resource id, cannot apply"));
        }
        if (!el[1].contains((ResourceIdParser.KEY_SEP))) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] keys = el[1].split(ResourceIdParser.KEY_CHK);
        if (keys.length < 2) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] parts = keys[1].split(ResourceIdParser.NM_CHK);
        if (parts.length < 3) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        if (parts[2].split("\\:").length != 3) {
            throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
        }
        return (new ResourceId.Builder()
                .addBranchPointSchema(el[0].split(ResourceIdParser.NM_CHK)[0],
                        el[0].split(ResourceIdParser.NM_CHK)[1])
                .addBranchPointSchema(keys[0].split(ResourceIdParser.NM_CHK)[0],
                        keys[0].split(ResourceIdParser.NM_CHK)[1])
                .addKeyLeaf(parts[0], parts[1], parts[2])
                .build());

    }

    /**
     * Retrieves device id from Resource id.
     *
     * @param path associated with the event
     * @return the deviceId of the effected device
     */
    @Beta
    public DeviceId getDeviceId(ResourceId path) {
        String resId = ResourceIdParser.parseResId(path);
        String[] el = resId.split(ResourceIdParser.EL_CHK);
        if (el.length < 2) {
            throw new RuntimeException(new NetconfException("Invalid resource id, cannot apply"));
        }
        if (!el[2].contains((ResourceIdParser.KEY_SEP))) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] keys = el[2].split(ResourceIdParser.KEY_CHK);
        if (keys.length < 2) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] parts = keys[1].split(ResourceIdParser.NM_CHK);
        if (parts.length < 3) {
            throw new RuntimeException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] temp = parts[2].split("\\:");
        String ip, port;
        if (temp.length != 3) {
            throw new RuntimeException(new NetconfException("Invalid device id form, cannot apply"));
        }
        ip = temp[1];
        port = temp[2];
        try {
            return DeviceId.deviceId(new URI("netconf", ip + ":" + port, (String) null));
        } catch (URISyntaxException ex) {
            throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, ex);
        }
    }

    /* Accumulates events to allow processing after a desired number of events were accumulated.
    */
    private class InternalEventAccummulator extends AbstractAccumulator<DynamicConfigEvent> {
        protected InternalEventAccummulator() {
            super(new Timer("dyncfgevt-timer"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
        }
        @Override
        public void processItems(List<DynamicConfigEvent> events) {
            Map<ResourceId, List<DynamicConfigEvent>> evtmap = new LinkedHashMap<>();
            Boolean handleEx = false; //hack
            ResourceId exId = null; //hack
            for (DynamicConfigEvent e : events) {
                checkNotNull(e, "process:Event cannot be null");
                ResourceId cur = e.subject();
                //TODO remove this hack after store ordering is fixed
                if (ResourceIdParser.parseResId(cur).compareTo(EXCPATH) == 0) {
                    if (e.type() == DynamicConfigEvent.Type.NODE_ADDED) {
                        log.info("Received an event for the xempted path ADD {}", e.type());
                        handleEx = true;
                        exId = cur;
                    } else {
                        log.warn("Received an event for the xempted path {}, NOT handled!!", e.type());
                    }
                } else { //actual code
                    ResourceId key = getDeviceKey(e.subject());
                    List<DynamicConfigEvent> el = evtmap.get(key);
                    if (el == null) {
                        el = new ArrayList<>();
                    }
                    el.add(e);
                    evtmap.put(key, el);
                }
            }
            evtmap.forEach((k, v) -> {
                log.info("Current deviceKey {}", k);
                DeviceId curDevice = getDeviceId(k);
                if (!isMaster(curDevice)) {
                    log.info("NetConfListener: not master, ignoring config for device {}", k);
                    return;
                }
                initiateConnection(curDevice);
                for (DynamicConfigEvent curEvt : v) {
                    switch (curEvt.type()) {
                        case NODE_ADDED:
                        case NODE_UPDATED:
                        case NODE_REPLACED:
                            Filter filt = new Filter();
                            DataNode node = cfgService.readNode(k, filt);
                            configUpdate(node, curDevice, k);
                            break;
                        case NODE_DELETED:
                            log.info("NetConfListener: RXD DELETE EVT for {}", k);
                            configDelete(null, curDevice, k); //TODO curEvt.subject());
                            break;
                        case UNKNOWN_OPRN:
                        default:
                            log.warn("NetConfListener: unknown event: {}", curEvt.type());
                            break;
                    }
                }
            });
            //TODO remove this hack after store ordering is fixed
            if (handleEx) {
                log.info("Handling exception path {}", exId);
                DeviceId exDevice = getDeviceId(exId);
                if (!isMaster(exDevice)) {
                    log.info("NetConfListener: not master, ignoring config for expath {}", exId);
                    return;
                }
                initiateConnection(exDevice);
                Filter filt = new Filter();
                DataNode exnode = cfgService.readNode(exId, filt);
                configUpdate(exnode, exDevice, exId);
            } //end of hack
        }
    }
}