/*
 * 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.provider.te.tunnel;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelDescription;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelProvider;
import org.onosproject.incubator.net.tunnel.TunnelProviderRegistry;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.Path;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.protocol.restconf.RestConfSBController;
import org.onosproject.protocol.restconf.RestconfNotificationEventListener;
import org.onosproject.provider.te.utils.DefaultJsonCodec;
import org.onosproject.provider.te.utils.YangCompositeEncodingImpl;
import org.onosproject.tetopology.management.api.TeTopology;
import org.onosproject.tetopology.management.api.TeTopologyKey;
import org.onosproject.tetopology.management.api.TeTopologyService;
import org.onosproject.tetunnel.api.TeTunnelProviderService;
import org.onosproject.tetunnel.api.TeTunnelService;
import org.onosproject.tetunnel.api.tunnel.DefaultTeTunnel;
import org.onosproject.tetunnel.api.tunnel.TeTunnel;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.rev20160705.IetfTe;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.rev20160705.ietfte.tunnelsgrouping.Tunnels;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.types.rev20160705.IetfTeTypes;
import org.onosproject.yms.ych.YangCodecHandler;
import org.onosproject.yms.ych.YangCompositeEncoding;
import org.onosproject.yms.ych.YangProtocolEncodingFormat;
import org.onosproject.yms.ymsm.YmsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.onosproject.provider.te.utils.CodecTools.jsonToString;
import static org.onosproject.provider.te.utils.CodecTools.toJson;
import static org.onosproject.tetopology.management.api.TeTopology.BIT_MERGED;
import static org.onosproject.teyang.utils.tunnel.TunnelConverter.buildIetfTe;
import static org.onosproject.teyang.utils.tunnel.TunnelConverter.yang2TeTunnel;
import static org.onosproject.yms.ych.YangProtocolEncodingFormat.JSON;
import static org.onosproject.yms.ych.YangResourceIdentifierType.URI;
import static org.onosproject.yms.ydt.YmsOperationType.EDIT_CONFIG_REQUEST;
import static org.onosproject.yms.ydt.YmsOperationType.QUERY_REPLY;


/**
 * Provider which uses RESTCONF to do cross-domain tunnel creation/deletion/
 * update/deletion and so on operations on the domain networks.
 */

@Component(immediate = true)
public class TeTunnelRestconfProvider extends AbstractProvider
        implements TunnelProvider {

    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final String SCHEMA = "ietf";
    private static final String IETF = "ietf";
    private static final String TE = "te";
    private static final int DEFAULT_INDEX = 1;
    private static final String TUNNELS = "tunnels";
    private static final String TUNNELS_URL = IETF + ":" + TE + "/" + TUNNELS;
    private static final String IETF_NOTIFICATION_URI = "netconf";
    private static final String MEDIA_TYPE_JSON = "json";

    private static final String SHOULD_IN_ONE = "Tunnel should be setup in one topo";
    private static final String PROVIDER_ID = "org.onosproject.provider.ietf";
    private static final String RESTCONF_ROOT = "/onos/restconf";
    private static final String TE_TUNNEL_KEY = "TeTunnelKey";

    //private final RestconfNotificationEventListener listener =
    //        new InternalTunnelNotificationListener();

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected RestConfSBController controller;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected YmsService ymsService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected TeTunnelService tunnelService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected TeTunnelProviderService providerService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected TeTopologyService topologyService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected TunnelProviderRegistry tunnelProviderRegistry;

    private YangCodecHandler codecHandler;

    @Activate
    public void activate() {
        tunnelProviderRegistry.register(this);
        codecHandler = ymsService.getYangCodecHandler();
        codecHandler.addDeviceSchema(IetfTe.class);
        codecHandler.addDeviceSchema(IetfTeTypes.class);
        codecHandler.registerOverriddenCodec(new DefaultJsonCodec(ymsService),
                                             YangProtocolEncodingFormat.JSON);
        collectInitialTunnels();
        subscribe();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        tunnelProviderRegistry.unregister(this);
        unsubscribe();
        log.info("Stopped");

    }

    public TeTunnelRestconfProvider() {
        super(new ProviderId(SCHEMA, PROVIDER_ID));
    }

    private void collectInitialTunnels() {
        for (DeviceId deviceId : controller.getDevices().keySet()) {
            ObjectNode jsonNodes = executeGetRequest(deviceId);
            if (jsonNodes == null) {
                continue;
            }
            ObjectNode tunnelsNode = (ObjectNode) jsonNodes.get(TUNNELS);
            if (tunnelsNode == null) {
                continue;
            }
            Tunnels teTunnels = getYangTunnelsObject(tunnelsNode);
            if (teTunnels == null) {
                continue;
            }
            updateTeTunnels(teTunnels);
        }
    }

    private void subscribe() {
        for (DeviceId deviceId : controller.getDevices().keySet()) {
            try {
                if (!controller.isNotificationEnabled(deviceId)) {
                    controller.enableNotifications(deviceId, IETF_NOTIFICATION_URI,
                                                   "application/json",
                                                   new InternalTunnelNotificationListener());
                } else {
                    controller.addNotificationListener(deviceId,
                                                       new InternalTunnelNotificationListener());
                }
            } catch (Exception e) {
                log.error("Failed to subscribe for {} : {}", deviceId,
                          e.getMessage());
            }
        }
    }

    private void unsubscribe() {
        controller.getDevices()
                .keySet()
                .forEach(deviceId -> controller
                        .removeNotificationListener(deviceId,
                                                    new InternalTunnelNotificationListener()));
    }

    @Override
    public void setupTunnel(Tunnel tunnel, Path path) {
        TeTunnel teTunnel = tunnelService.getTeTunnel(tunnel.tunnelId());
        long tid = teTunnel.srcNode().topologyId();
        checkState(tid == teTunnel.dstNode().topologyId(), SHOULD_IN_ONE);
        setupTunnel(getOwnDevice(tid), tunnel, path);
    }

    @Override
    public void setupTunnel(ElementId srcElement, Tunnel tunnel, Path path) {
        if (!tunnel.annotations().keys().contains(TE_TUNNEL_KEY)) {
            log.warn("No tunnel key info in tunnel {}", tunnel);
            return;
        }

        String teTunnelKey = tunnel.annotations().value(TE_TUNNEL_KEY);

        Optional<TeTunnel> optTunnel = tunnelService.getTeTunnels()
                .stream()
                .filter(t -> t.teTunnelKey().toString().equals(teTunnelKey))
                .findFirst();

        if (!optTunnel.isPresent()) {
            log.warn("No te tunnel map to tunnel {}", tunnel);
            return;
        }

        IetfTe ietfTe = buildIetfTe(optTunnel.get(), true);

        YangCompositeEncoding encoding = codecHandler.
                encodeCompositeOperation(RESTCONF_ROOT, null, ietfTe,
                                         JSON, EDIT_CONFIG_REQUEST);
        String identifier = encoding.getResourceIdentifier();
        String resourceInformation = encoding.getResourceInformation();

        if (srcElement == null) {
            log.error("Can't find remote device for tunnel : {}", tunnel);
            return;
        }
        controller.post((DeviceId) srcElement, identifier,
                        new ByteArrayInputStream(resourceInformation.getBytes()),
                        MEDIA_TYPE_JSON, ObjectNode.class);
    }

    @Override
    public void releaseTunnel(Tunnel tunnel) {
        //TODO implement release tunnel method
    }

    @Override
    public void releaseTunnel(ElementId srcElement, Tunnel tunnel) {
        //TODO implement release tunnel with src method
    }

    @Override
    public void updateTunnel(Tunnel tunnel, Path path) {
        //TODO implement update tunnel method

    }

    @Override
    public void updateTunnel(ElementId srcElement, Tunnel tunnel, Path path) {
        //TODO implement update tunnel with src method
    }

    @Override
    public TunnelId tunnelAdded(TunnelDescription tunnel) {
        //TODO implement tunnel add method when te tunnel app merged to core
        return null;
    }

    @Override
    public void tunnelRemoved(TunnelDescription tunnel) {
        //TODO implement tunnel remove method when te tunnel app merged to core

    }

    @Override
    public void tunnelUpdated(TunnelDescription tunnel) {
        //TODO implement tunnel update method when te tunnel app merged to core
    }

    @Override
    public Tunnel tunnelQueryById(TunnelId tunnelId) {
        return null;
    }

    private ObjectNode executeGetRequest(DeviceId deviceId) {
        //the request url is ietf-te:te/tunnels
        //the response node will begin with tunnels
        //be careful here to when get the tunnels data
        InputStream resultStream =
                controller.get(deviceId, TUNNELS_URL, MEDIA_TYPE_JSON);
        return toJson(resultStream);
    }

    private Tunnels getYangTunnelsObject(ObjectNode tunnelsNode) {
        checkNotNull(tunnelsNode, "Input object node should not be null");

        YangCompositeEncoding yce =
                new YangCompositeEncodingImpl(URI,
                                              TUNNELS_URL,
                                              jsonToString(tunnelsNode));

        Object yo = codecHandler.decode(yce, JSON, QUERY_REPLY);

        if (yo == null) {
            log.error("YMS decoder returns null");
            return null;
        }
        IetfTe ietfTe = null;
        Tunnels tunnels = null;
        if (yo instanceof List) {
            List<Object> list = (List<Object>) yo;
            ietfTe = (IetfTe) list.get(DEFAULT_INDEX);
        }
        if (ietfTe != null && ietfTe.te() != null) {
            tunnels = ietfTe.te().tunnels();
        }
        return tunnels;
    }

    private void updateTeTunnels(Tunnels tunnels) {
        TeTopologyKey key = getTopologyKey();

        tunnels.tunnel().forEach(tunnel -> {
            DefaultTeTunnel teTunnel = yang2TeTunnel(tunnel, key);
            providerService.updateTeTunnel(teTunnel);
        });
    }

    private TeTopologyKey getTopologyKey() {
        TeTopologyKey key = null;
        Optional<TeTopology> teTopology = topologyService.teTopologies()
                .teTopologies()
                .values()
                .stream()
                .filter(topology -> topology.flags().get(BIT_MERGED))
                .findFirst();
        if (teTopology.isPresent()) {
            TeTopology topology = teTopology.get();
            key = topology.teTopologyId();
        }
        return key;
    }

    private DeviceId getOwnDevice(long topologyId) {
        DeviceId deviceId = null;
        Optional<TeTopology> topoOpt = topologyService.teTopologies()
                .teTopologies()
                .values()
                .stream()
                .filter(tp -> tp.teTopologyId().topologyId() == topologyId)
                .findFirst();

        if (topoOpt.isPresent()) {
            deviceId = topoOpt.get().ownerId();
        }
        return deviceId;
    }


    private class InternalTunnelNotificationListener implements
            RestconfNotificationEventListener {

        @Override
        public void handleNotificationEvent(DeviceId deviceId, Object eventJsonString) {
            ObjectNode response = toJson((String) eventJsonString);
            if (response == null) {
                return;
            }
            JsonNode teNode = response.get(TE);
            if (teNode == null) {
                log.error("Illegal te json object from {}", deviceId);
                return;
            }
            JsonNode tunnelsNode = teNode.get(TUNNELS);
            if (tunnelsNode == null) {
                log.error("Illegal tunnel json object from {}", deviceId);
                return;
            }

            Tunnels tunnels = getYangTunnelsObject((ObjectNode) tunnelsNode);
            if (tunnels == null) {
                return;
            }
            updateTeTunnels(tunnels);
        }
    }
}
