/*
 * Copyright 2015-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.rest.resources;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.util.IntentFilter;
import org.onosproject.net.intent.util.IntentMiniSummary;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.onlab.util.Tools.nullIsNotFound;
import static org.onosproject.net.intent.IntentState.FAILED;
import static org.onosproject.net.intent.IntentState.WITHDRAWN;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Query, submit and withdraw network intents.
 */
@Path("intents")
public class IntentsWebResource extends AbstractWebResource {

    private static final Logger log = getLogger(IntentsWebResource.class);
    private static final int WITHDRAW_EVENT_TIMEOUT_SECONDS = 5;

    private static final String APP_ID_NOT_FOUND = "Application Id not found";
    private static final String HOST_TO_HOST_INTENT = "HostToHostIntent";
    private static final String POINT_TO_POINT_INTENT = "PointToPointIntent";
    private static final String SINGLE_TO_MULTI_POINT_INTENT =
            "SinglePointToMultiPointIntent";
    private static final String MULTI_TO_SINGLE_POINT_INTENT =
            "MultiPointToSinglePointIntent";

    private static final String INTENT = "Intent";
    private static final String APP_ID = "appId";
    private static final String ID = "id";
    private static final String INTENT_PATHS = "paths";
    private static final String INTENT_TYPE = "type";
    private static final String INTENT_NOT_FOUND = "Intent is not found";

    @Context
    private UriInfo uriInfo;

    /**
     * Gets all intents.
     * Returns array containing all the intents in the system.
     *
     * @return 200 OK with array of all the intents in the system
     * @onos.rsModel Intents
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getIntents() {
        final Iterable<Intent> intents = get(IntentService.class).getIntents();
        final ObjectNode root = encodeArray(Intent.class, "intents", intents);
        return ok(root).build();
    }


    /**
     * Gets Summary of all intents.
     * Returns Summary of the intents in the system.
     *
     * @return 200 OK with Summary of all the intents in the system
     * @onos.rsModel Minisummary
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("minisummary")
    public Response getIntentSummary() {
        final Iterable<Intent> intents = get(IntentService.class).getIntents();
        ObjectNode root = mapper().createObjectNode();
        IntentMiniSummary intentminisummary = new IntentMiniSummary();
        Map<String, IntentMiniSummary> map = intentminisummary.summarize(intents, get(IntentService.class));
        map.values().stream().forEach(intentsummary -> {
            root.put(intentsummary.getIntentType(), codec(IntentMiniSummary.class).encode(intentsummary, this));
        });
        return ok(root).build();
    }


    /**
     * Gets intent installables by application ID and key.
     * @param appId application identifier
     * @param key   intent key
     *
     * @return 200 OK with array of the intent installables
     * @onos.rsModel Intents
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("installables/{appId}/{key}")
    public Response getIntentWithInstallable(@PathParam("appId") String appId,
                                             @PathParam("key") String key) {
        final IntentService intentService = get(IntentService.class);
        final ApplicationId app = get(CoreService.class).getAppId(appId);
        nullIsNotFound(app, APP_ID_NOT_FOUND);

        Intent intent = intentService.getIntent(Key.of(key, app));
        if (intent == null) {
            long numericalKey = Long.decode(key);
            intent = intentService.getIntent(Key.of(numericalKey, app));
        }
        nullIsNotFound(intent, INTENT_NOT_FOUND);

        final Iterable<Intent> installables = intentService.getInstallableIntents(intent.key());
        final ObjectNode root = encodeArray(Intent.class, "installables", installables);
        return ok(root).build();
    }

    /**
     * Gets intent by application and key.
     * Returns details of the specified intent.
     *
     * @param appId application identifier
     * @param key   intent key
     * @return 200 OK with intent data
     * @onos.rsModel Intents
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{appId}/{key}")
    public Response getIntentById(@PathParam("appId") String appId,
                                  @PathParam("key") String key) {
        final ApplicationId app = get(CoreService.class).getAppId(appId);
        nullIsNotFound(app, APP_ID_NOT_FOUND);
        Intent intent = get(IntentService.class).getIntent(Key.of(key, app));
        if (intent == null) {
            long numericalKey = Long.decode(key);
            intent = get(IntentService.class).getIntent(Key.of(numericalKey, app));
        }
        nullIsNotFound(intent, INTENT_NOT_FOUND);

        final ObjectNode root;
        if (intent instanceof HostToHostIntent) {
            root = codec(HostToHostIntent.class).encode((HostToHostIntent) intent, this);
        } else if (intent instanceof PointToPointIntent) {
            root = codec(PointToPointIntent.class).encode((PointToPointIntent) intent, this);
        } else if (intent instanceof SinglePointToMultiPointIntent) {
            root = codec(SinglePointToMultiPointIntent.class).encode((SinglePointToMultiPointIntent) intent, this);
        } else if (intent instanceof MultiPointToSinglePointIntent) {
            root = codec(MultiPointToSinglePointIntent.class).encode((MultiPointToSinglePointIntent) intent, this);
        } else {
            root = codec(Intent.class).encode(intent, this);
        }
        return ok(root).build();
    }

    /**
     * Gets all related flow entries created by a particular intent.
     * Returns all flow entries of the specified intent.
     *
     * @param appId application identifier
     * @param key   intent key
     * @return 200 OK with intent data
     * @onos.rsModel Relatedflows
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("relatedflows/{appId}/{key}")
    public Response getIntentFlowsById(@PathParam("appId") String appId,
                                       @PathParam("key") String key) {
        ApplicationId applicationId = get(CoreService.class).getAppId(appId);
        nullIsNotFound(applicationId, APP_ID_NOT_FOUND);
        IntentService intentService = get(IntentService.class);
        FlowRuleService flowService = get(FlowRuleService.class);

        Intent intent = intentService.getIntent(Key.of(key, applicationId));
        if (intent == null) {
            long numericalKey = Long.decode(key);
            intent = intentService.getIntent(
                    Key.of(numericalKey, applicationId));
        }
        nullIsNotFound(intent, INTENT_NOT_FOUND);

        ObjectNode root = mapper().createObjectNode();
        root.put(APP_ID, appId);
        root.put(ID, key);

        IntentFilter intentFilter = new IntentFilter(intentService, flowService);

        List<Intent> installables =
                intentService.getInstallableIntents(intent.key());

        if (intent instanceof HostToHostIntent) {
            root.put(INTENT_TYPE, HOST_TO_HOST_INTENT);
        } else if (intent instanceof PointToPointIntent) {
            root.put(INTENT_TYPE, POINT_TO_POINT_INTENT);
        } else if (intent instanceof SinglePointToMultiPointIntent) {
            root.put(INTENT_TYPE, SINGLE_TO_MULTI_POINT_INTENT);
        } else if (intent instanceof MultiPointToSinglePointIntent) {
            root.put(INTENT_TYPE, MULTI_TO_SINGLE_POINT_INTENT);
        } else {
            root.put(INTENT_TYPE, INTENT);
        }

        ArrayNode pathsNode = root.putArray(INTENT_PATHS);

        for (List<FlowEntry> flowEntries :
                intentFilter.readIntentFlows(installables)) {
            ArrayNode flowNode = pathsNode.addArray();

            for (FlowEntry entry : flowEntries) {
                flowNode.add(codec(FlowEntry.class).encode(entry, this));
            }
        }
        return ok(root).build();
    }

    /**
     * Internal listener for tracking the intent deletion events.
     */
    private class DeleteListener implements IntentListener {
        final Key key;
        final CountDownLatch latch;

        /**
         * Default constructor.
         *
         * @param key   key
         * @param latch count down latch
         */
        DeleteListener(Key key, CountDownLatch latch) {
            this.key = key;
            this.latch = latch;
        }

        @Override
        public void event(IntentEvent event) {
            if (Objects.equals(event.subject().key(), key) &&
                    (event.type() == IntentEvent.Type.WITHDRAWN ||
                            event.type() == IntentEvent.Type.FAILED)) {
                latch.countDown();
            }
        }
    }

    /**
     * Submits a new intent.
     * Creates and submits intent from the JSON request.
     *
     * @param stream input JSON
     * @return status of the request - CREATED if the JSON is correct,
     * BAD_REQUEST if the JSON is invalid
     * @onos.rsModel IntentHost
     */
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createIntent(InputStream stream) {
        try {
            IntentService service = get(IntentService.class);
            ObjectNode root = (ObjectNode) mapper().readTree(stream);
            Intent intent = codec(Intent.class).decode(root, this);
            service.submit(intent);
            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
                    .path("intents")
                    .path(intent.appId().name())
                    .path(Long.toString(intent.id().fingerprint()));
            return Response
                    .created(locationBuilder.build())
                    .build();
        } catch (IOException ioe) {
            throw new IllegalArgumentException(ioe);
        }
    }

    /**
     * Withdraws intent.
     * Withdraws the specified intent from the system.
     *
     * @param appId application identifier
     * @param key   intent key
     * @return 204 NO CONTENT
     */
    @DELETE
    @Path("{appId}/{key}")
    public Response deleteIntentById(@PathParam("appId") String appId,
                                     @PathParam("key") String key) {
        final ApplicationId app = get(CoreService.class).getAppId(appId);
        nullIsNotFound(app, APP_ID_NOT_FOUND);
        Intent intent = get(IntentService.class).getIntent(Key.of(key, app));
        IntentService service = get(IntentService.class);

        if (intent == null) {
            intent = service
                    .getIntent(Key.of(Long.decode(key), app));
        }
        if (intent == null) {
            // No such intent.  REST standards recommend a positive status code
            // in this case.
            return Response.noContent().build();
        }

        Key k = intent.key();

        // set up latch and listener to track uninstall progress
        CountDownLatch latch = new CountDownLatch(1);

        IntentListener listener = new DeleteListener(k, latch);
        service.addListener(listener);

        try {
            // request the withdraw
            service.withdraw(intent);

            try {
                latch.await(WITHDRAW_EVENT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                log.info("REST Delete operation timed out waiting for intent {}", k);
                Thread.currentThread().interrupt();
            }
            // double check the state
            IntentState state = service.getIntentState(k);
            if (state == WITHDRAWN || state == FAILED) {
                service.purge(intent);
            }

        } finally {
            // clean up the listener
            service.removeListener(listener);
        }
        return Response.noContent().build();
    }
}
