/*
 * 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.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.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

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();
        //TODO this is a blocking call on ADVA OLS, right now using cache.
//        RestSBController controller = checkNotNull(handler().get(RestSBController.class));
//        ObjectMapper om = new ObjectMapper();
//        final ObjectReader reader = om.reader();
//        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();
//        }
        List<FlowEntry> entries = new ArrayList<>();
        Set<FlowRule> rules = getConnectionCache().get(deviceId);
        if (rules != null) {
            rules.forEach(rule -> {
                entries.add(new DefaultFlowEntry(rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
            });
        }
        return entries;
    }

    @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) {
                CompletableFuture<Integer>  flowInstallation =
                        CompletableFuture.supplyAsync(() -> controller.post(deviceId, CONN_REQ_POST_API,
                        new ByteArrayInputStream(applyConnectivityRequest.toByteArray()),
                        MediaType.APPLICATION_JSON_TYPE));
                flowInstallation.thenApply(result -> {
                    if (result == HttpStatus.SC_CREATED) {
                        getConnectionCache().add(deviceId, uuid, flowRule);
                        added.add(flowRule);
                    } else {
                       log.error("Can't add flow {}, result {}", flowRule, result);
                    }
                    return result;
                });
                // 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.
            }
        });
        //TODO workaround for blocking call on ADVA OLS should return added
        return rules;
    }

    @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;
            }
            CompletableFuture<Integer>  flowInstallation =
                    CompletableFuture.supplyAsync(() -> controller.delete(deviceId,
                            CONN_REQ_REMOVE_DATA_API + conn.getId(),
                            null, MediaType.APPLICATION_JSON_TYPE));
            flowInstallation.thenApply(result -> {
                if (result == HttpStatus.SC_NO_CONTENT) {
                    getConnectionCache().remove(deviceId, flowRule);
                    removed.add(flowRule);
                } else {
                    log.error("Can't remove flow {}, result {}", flowRule, result);
                }
                return result;
            });
        });
        //TODO workaround for blocking call on ADVA OLS shoudl return removed
        return rules;
    }

    /**
     * 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("Can't 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();
    }
}
