/*
 * Copyright 2018-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.
 *
 * This work was partially supported by EC H2020 project METRO-HAUL (761727).
 */
package org.onosproject.drivers.odtn.tapi;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onlab.packet.ChassisId;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.protocol.rest.RestSBController;
import org.slf4j.Logger;

import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LAYER_PROTOCOL_NAME;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MC_POOL;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_LAYER_QUALIFIER_NMC;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_MEDIA;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_INTERFACE_POINT;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SUPPORTED_LAYER_PROTOCOL_QUALIFIER;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.UUID;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.getOchSignal;
import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Driver Implementation of the DeviceDescrption discovery for ONF Transport-API (TAPI) v2.1 based
 * open line systems (OLS).
 */

public class TapiDeviceDescriptionDiscovery
        extends AbstractHandlerBehaviour
        implements DeviceDescriptionDiscovery {

    private static final Logger log = getLogger(TapiDeviceDescriptionDiscovery.class);
    private static final String SIP_REQUEST_DATA_API = "/restconf/data/tapi-common:context";

    /**
     * Get the deviceId for which the methods apply.
     *
     * @return The deviceId as contained in the handler data
     */
    private DeviceId did() {
        return handler().data().deviceId();
    }

    @Override
    public DeviceDescription discoverDeviceDetails() {
        log.debug("Getting device description");
        DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
        DeviceId deviceId = handler().data().deviceId();
        Device device = deviceService.getDevice(deviceId);

        if (device == null) {
            //TODO need to obtain from the device.
            return new DefaultDeviceDescription(deviceId.uri(),
                    Device.Type.OLS,
                    "Tapi",
                    "0",
                    "2.1",
                    "Unknown",
                    new ChassisId());
        } else {
            return new DefaultDeviceDescription(device.id().uri(),
                    Device.Type.OLS,
                    device.manufacturer(),
                    device.hwVersion(),
                    device.swVersion(),
                    device.serialNumber(),
                    device.chassisId());
        }
    }

    @Override
    public List<PortDescription> discoverPortDetails() {
        log.debug("Discovering port details.");
        RestSBController controller = checkNotNull(handler().get(RestSBController.class));
        DeviceId deviceId = handler().data().deviceId();

        try {
            InputStream inputStream = controller.get(deviceId, SIP_REQUEST_DATA_API, MediaType.APPLICATION_JSON_TYPE);
            JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
            if (jsonNode == null) {
                log.error("Can't discover port details at {}", SIP_REQUEST_DATA_API);
                return ImmutableList.of();
            }
            return parseTapiPorts(jsonNode);
        } catch (IOException e) {
            log.error("Exception discoverPortDetails() {}", did(), e);
            return ImmutableList.of();
        }
    }

    protected List<PortDescription> parseTapiPorts(JsonNode tapiContext) {
        List<PortDescription> ports = Lists.newArrayList();
        /*
         This annotations are used to store persistent mapping information between TAPI SIP's uuid
         and ONOS device portNumbers. This is needed to be publicly available at least within ODTN app
         when connectivity services will be sent to OLS Controller.
         */
        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
        Iterator<JsonNode> iter = tapiContext.get(SERVICE_INTERFACE_POINT).iterator();
        while (iter.hasNext()) {
            JsonNode sipAttributes = iter.next();
            if (checkValidEndpoint(sipAttributes)) {
                String uuid = sipAttributes.get(UUID).textValue();
                PortNumber portNumber = PortNumber.portNumber(uuid.split("-")[0]);
                annotations.set(UUID, uuid);

                JsonNode mcPool = sipAttributes.get(MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC).get(MC_POOL);
                // We get the first OCH signal as reported by the device.
                OchSignal ochSignal = getOchSignal(mcPool).iterator().next();
                //add och port
                ports.add(ochPortDescription(portNumber, true, OduSignalType.ODU4,
                        false, ochSignal, annotations.build()));


            } else {
                log.error("SIP {} is not valid", sipAttributes);
            }
        }
        log.debug("PortList: {}", ports);
        return ImmutableList.copyOf(ports);
    }

    /**
     * Create a filter method to identify just valid OLS SIPs.This method must check the
     * tapi object: "layer-protocol-name" and matching only if equals to "PHOTONIC-MEDIA" SIPs.
     * Moreover,the filtering could be enhanced by reading also:
     * "supported-layer-protocol-qualifier", to identify valid protocol-qualifier values such:
     * [PHOTONIC_LAYER_QUALIFIER_NMC, PHOTONIC_LAYER_QUALIFIER_NMCA, PHOTONIC_LAYER_QUALIFIER_OTSI...]
     **/
    private boolean checkValidEndpoint(JsonNode sipAttributes) {
        return sipAttributes.has(LAYER_PROTOCOL_NAME) &&
                sipAttributes.get(LAYER_PROTOCOL_NAME).toString().contains(PHOTONIC_MEDIA) &&
                sipAttributes.has(SUPPORTED_LAYER_PROTOCOL_QUALIFIER) &&
                sipAttributes.get(SUPPORTED_LAYER_PROTOCOL_QUALIFIER).toString()
                        .contains(PHOTONIC_LAYER_QUALIFIER_NMC);
    }

}
