/*
 * Copyright 2017-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.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.model.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";
    private static final String DEF_IP = "0:0:0"; //hack, remove later

    //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)
            .addKeyLeaf(DEVICE_ID, DEVNMSPACE, DEF_IP)
            .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);
        refId = refId.substring(0, refId.length() - (DEF_IP.length() + 1));
        if (!resId.contains(refId)) {
            return false;
        }
        if (resId.length() < refId.length()) {
            return false;
        }
        return (resId.substring(0, (refId.length())).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) {
            log.debug("parseAndEdit()", e);
            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 IllegalStateException(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 IllegalStateException(new NetconfException("Invalid device id form, cannot apply"));
            }
            ip = temp[1];
            port = temp[2];
        } else {
            throw new IllegalStateException(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 IllegalStateException(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 < 3) {
            throw new IllegalStateException(new NetconfException("Invalid resource id, cannot apply"));
        }
        if (!el[2].contains((ResourceIdParser.KEY_SEP))) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] keys = el[2].split(ResourceIdParser.KEY_CHK);
        if (keys.length < 2) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] parts = keys[1].split(ResourceIdParser.NM_CHK);
        if (parts.length < 3) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        if (parts[2].split("\\:").length != 3) {
            throw new IllegalStateException(new NetconfException("Invalid device id form, cannot apply"));
        }
        return (new ResourceId.Builder()
                .addBranchPointSchema(el[1].split(ResourceIdParser.NM_CHK)[0],
                        el[1].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 < 3) {
            throw new IllegalStateException(new NetconfException("Invalid resource id, cannot apply"));
        }
        if (!el[2].contains((ResourceIdParser.KEY_SEP))) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] keys = el[2].split(ResourceIdParser.KEY_CHK);
        if (keys.length < 2) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] parts = keys[1].split(ResourceIdParser.NM_CHK);
        if (parts.length < 3) {
            throw new IllegalStateException(new NetconfException("Invalid device id key, cannot apply"));
        }
        String[] temp = parts[2].split("\\:");
        String ip, port;
        if (temp.length != 3) {
            throw new IllegalStateException(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
                String expat = ResourceIdParser.parseResId(cur);
                if ((expat.compareTo(EXCPATH) == 0) && (e.type() == DynamicConfigEvent.Type.NODE_ADDED)) {
                        handleEx = true;
                        exId = cur;
                } 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) -> {
                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 = Filter.builder().build();
                            DataNode node = cfgService.readNode(k, filt);
                            configUpdate(node, curDevice, k);
                            break;
                        case NODE_DELETED:
                            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) {
                DeviceId exDevice = getDeviceId(exId);
                if (!isMaster(exDevice)) {
                    log.info("NetConfListener: not master, ignoring config for expath {}", exId);
                    return;
                }
                initiateConnection(exDevice);
                Filter filt = Filter.builder().build();
                DataNode exnode = cfgService.readNode(exId, filt);
                configUpdate(exnode, exDevice, exId);
            } //end of hack
        }
    }
}