/*
 * 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.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.google.common.collect.ImmutableList;
import org.apache.http.HttpStatus;
import org.onosproject.drivers.odtn.impl.DeviceConnection;
import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.protocol.rest.RestSBController;
import org.slf4j.Logger;

import javax.ws.rs.core.MediaType;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.END_POINT;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LAYER_PROTOCOL_NAME;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LAYER_PROTOCOL_QUALIFIER;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LOCAL_ID;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_MEDIA;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.POINT_TO_POINT_CONNECTIVITY;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_INTERFACE_POINT;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_INTERFACE_POINT_UUID;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_LAYER;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_TYPE;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.TAPI_CONNECTIVITY_CONNECTIVITY_SERVICE;
import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.TAPI_PHOTONIC_MEDIA_PHOTONIC_LAYER_QUALIFIER_NMC;
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 TapiFlowRuleProgrammable extends AbstractHandlerBehaviour
        implements FlowRuleProgrammable {

    private static final Logger log = getLogger(TapiFlowRuleProgrammable.class);
    private static final String CONN_REQ_POST_API = "/restconf/data/tapi-common:context/" +
            "tapi-connectivity:connectivity-context/";
    private static final String CONN_REQ_REMOVE_DATA_API = "/restconf/data/tapi-common:context/" +
            "tapi-connectivity:connectivity-context/connectivity-service=";
    private static final String CONN_REQ_GET_API = "/restconf/data/tapi-common:context/" +
            "tapi-connectivity:connectivity-context/";


    @Override
    public Collection<FlowEntry> getFlowEntries() {
        DeviceId deviceId = did();
        RestSBController controller = checkNotNull(handler().get(RestSBController.class));
        ObjectMapper om = new ObjectMapper();
        final ObjectReader reader = om.reader();
        // all waveserver responses contain data node, which contains the requested data
        InputStream response = controller.get(deviceId, CONN_REQ_GET_API, MediaType.APPLICATION_JSON_TYPE);
        JsonNode jsonNode = null;
        try {
            jsonNode = reader.readTree(response);
            if (jsonNode == null) {
                log.error("JsonNode is null for response {}", response);
                return ImmutableList.of();
            }
            Set<String> uuids = parseTapiGetConnectivityRequest(jsonNode);
            DeviceConnectionCache cache = getConnectionCache();
            if (cache.get(deviceId) == null) {
                return ImmutableList.of();
            }
            List<FlowEntry> entries = new ArrayList<>();
            uuids.forEach(uuid -> {
                FlowRule rule = cache.get(deviceId, uuid);
                if (rule != null) {
                    entries.add(new DefaultFlowEntry(rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
                } else {
                    log.info("Non existing rule for uuid {}", uuid);
                }
            });
            return entries;
        } catch (IOException e) {
            return ImmutableList.of();
        }
    }

    @Override
    public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
        DeviceId deviceId = handler().data().deviceId();
        RestSBController controller = checkNotNull(handler().get(RestSBController.class));
        ImmutableList.Builder<FlowRule> added = ImmutableList.builder();
        rules.forEach(flowRule -> {
            String uuid = createUuid();
            ByteArrayOutputStream applyConnectivityRequest = createConnectivityRequest(uuid, flowRule);
            if (applyConnectivityRequest.size() != 0) {
                int result = controller.post(deviceId, CONN_REQ_POST_API,
                        new ByteArrayInputStream(applyConnectivityRequest.toByteArray()),
                        MediaType.APPLICATION_JSON_TYPE);
                // TODO retrieve the UUID from the location and store with that identifier
                // at the moment is implied that the sent one is the same used by the TAPI server.
                if (result == HttpStatus.SC_CREATED) {
                    getConnectionCache().add(deviceId, uuid, flowRule);
                    added.add(flowRule);
                }
            }
        });
        return added.build();
    }

    @Override
    public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
        DeviceId deviceId = handler().data().deviceId();
        RestSBController controller = checkNotNull(handler().get(RestSBController.class));
        ImmutableList.Builder<FlowRule> removed = ImmutableList.builder();
        rules.forEach(flowRule -> {
            DeviceConnection conn = getConnectionCache().get(deviceId, flowRule.id());
            if (conn == null || conn.getId() == null) {
                log.warn("Can't find associate device connection for flow {} and device {}",
                        flowRule.id(), deviceId);
                return;
            }
            int result = controller.delete(deviceId, CONN_REQ_REMOVE_DATA_API + conn.getId(),
                    null, MediaType.APPLICATION_JSON_TYPE);
            if (result == HttpStatus.SC_NO_CONTENT) {
                getConnectionCache().remove(deviceId, flowRule);
                removed.add(flowRule);
            }
        });
        return removed.build();
    }

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

    private DeviceConnectionCache getConnectionCache() {
        return DeviceConnectionCache.init();
    }

    protected Set<String> parseTapiGetConnectivityRequest(JsonNode tapiConnectivityReply) {
        /*
         {
            "tapi-connectivity:connectivity-service":[
                {
                    "uuid":"ffb006d4-349e-4d2f-817e-0906c88458d0",
                    <other fields>
                }
            ]
          }
         */
        Set<String> uuids = new HashSet<>();
        if (tapiConnectivityReply.has(TAPI_CONNECTIVITY_CONNECTIVITY_SERVICE)) {
            tapiConnectivityReply.get(TAPI_CONNECTIVITY_CONNECTIVITY_SERVICE).elements()
                    .forEachRemaining(node -> uuids.add(node.get(TapiDeviceHelper.UUID).asText()));
        } else {
            log.warn("Cant retrieve connectivity UUID from {}", tapiConnectivityReply);
        }
        //This is only one uuid or empty in case of failures
        return uuids;
    }

    ByteArrayOutputStream createConnectivityRequest(String uuid, FlowRule rule) {
        /*
        {
            "tapi-connectivity:connectivity-service":[
                {
                    "uuid":"ffb006d4-349e-4d2f-817e-0906c88458d0",
                    "service-layer":"PHOTONIC_MEDIA",
                    "service-type":"POINT_TO_POINT_CONNECTIVITY",
                    "end-point":[
                        {
                            "local-id":"1",
                            "layer-protocol-name":"PHOTONIC_MEDIA",
                            "layer-protocol-qualifier":"tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
                            "service-interface-point":{
                                "service-interface-point-uuid":"0923962e-b83f-4702-9b16-a1a0db0dc1f9"
                            }
                        },
                        {
                            "local-id":"2",
                            "layer-protocol-name":"PHOTONIC_MEDIA",
                            "layer-protocol-qualifier":"tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
                            "service-interface-point":{
                                "service-interface-point-uuid":"76be95de-5769-4e5d-b65e-62cb6c39cf6b "
                            }
                        }
                    ]
               }
           ]
        }
        */
        DeviceService deviceService = handler().get(DeviceService.class);
        PortCriterion inputPortCriterion = (PortCriterion) checkNotNull(rule.selector()
                .getCriterion(Criterion.Type.IN_PORT));
        String inputPortUuid = deviceService.getPort(rule.deviceId(),
                inputPortCriterion.port()).annotations().value(TapiDeviceHelper.UUID);

        Instructions.OutputInstruction outInstruction = (Instructions.OutputInstruction) checkNotNull(rule.treatment()
                .allInstructions().stream().filter(instr -> instr.type().equals(Instruction.Type.OUTPUT))
                .findFirst().orElse(null));
        String outputPortUuid = deviceService.getPort(rule.deviceId(),
                outInstruction.port()).annotations().value(TapiDeviceHelper.UUID);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            JsonGenerator generator = getJsonGenerator(stream);
            generator.writeStartObject();
            generator.writeArrayFieldStart(TAPI_CONNECTIVITY_CONNECTIVITY_SERVICE);
            generator.writeStartObject();
            generator.writeStringField(TapiDeviceHelper.UUID, uuid);
            generator.writeStringField(SERVICE_LAYER, PHOTONIC_MEDIA);
            generator.writeStringField(SERVICE_TYPE, POINT_TO_POINT_CONNECTIVITY);
            generator.writeArrayFieldStart(END_POINT);
            addEndPoint(generator, inputPortUuid);
            addEndPoint(generator, outputPortUuid);
            generator.writeEndArray();
            generator.writeEndObject();
            generator.writeEndArray();
            generator.writeEndObject();
            generator.close();
            return stream;
        } catch (IOException e) {
            log.error("Cant' create json", e);
        }
        return stream;
    }

    private JsonGenerator getJsonGenerator(ByteArrayOutputStream stream) throws IOException {
        JsonFactory factory = new JsonFactory();
        return factory.createGenerator(stream, JsonEncoding.UTF8);
    }
    /*
    {
          "local-id":"1",
          "layer-protocol-name":"PHOTONIC_MEDIA",
          "layer-protocol-qualifier":"tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC",
          "service-interface-point":{
                "service-interface-point-uuid":"0923962e-b83f-4702-9b16-a1a0db0dc1f9"
         }
     }
     */
    private void addEndPoint(JsonGenerator generator, String sipUuid) throws IOException {
        generator.writeStartObject();
        generator.writeStringField(LOCAL_ID, sipUuid);
        generator.writeStringField(LAYER_PROTOCOL_NAME, PHOTONIC_MEDIA);
        generator.writeStringField(LAYER_PROTOCOL_QUALIFIER,
                TAPI_PHOTONIC_MEDIA_PHOTONIC_LAYER_QUALIFIER_NMC);
        generator.writeObjectFieldStart(SERVICE_INTERFACE_POINT);
        generator.writeStringField(SERVICE_INTERFACE_POINT_UUID, sipUuid);
        generator.writeEndObject();
        generator.writeEndObject();
    }

    private String createUuid() {
        return UUID.randomUUID().toString();
    }
}
