/*
 * 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.onlab.util.Tools.readTreeFromStream;
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 = readTreeFromStream(mapper(), 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);
            }
            // 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();
    }
}
