/*
 * Copyright 2014-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.cli.net;

import com.google.common.collect.ImmutableList;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.api.action.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.app.ApplicationIdWithIntentNameCompleter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.EnumSet;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.net.intent.IntentState.FAILED;
import static org.onosproject.net.intent.IntentState.WITHDRAWN;

/**
 * Removes an intent.
 */
@Service
@Command(scope = "onos", name = "remove-intent",
        description = "Removes the specified intent")
public class IntentRemoveCommand extends AbstractShellCommand {

    @Argument(index = 0, name = "app",
            description = "Application ID",
            required = false, multiValued = false)
    @Completion(ApplicationIdWithIntentNameCompleter.class)
    String applicationIdString = null;

    @Argument(index = 1, name = "key",
            description = "Intent Key",
            required = false, multiValued = false)
    @Completion(IntentKeyCompleter.class)
    String keyString = null;

    @Option(name = "-p", aliases = "--purge",
            description = "Purge the intent from the store after removal",
            required = false, multiValued = false)
    private boolean purgeAfterRemove = false;

    @Option(name = "-s", aliases = "--sync",
            description = "Waits for the removal before returning",
            required = false, multiValued = false)
    private boolean sync = false;

    private static final EnumSet<IntentState> CAN_PURGE = EnumSet.of(WITHDRAWN, FAILED);

    @Override
    protected void doExecute() {
        IntentService intentService = get(IntentService.class);
        removeIntent(intentService.getIntents(),
             applicationIdString, keyString,
             purgeAfterRemove, sync);
    }

    /**
     * Purges the intents passed as argument.
     *
     * @param intents list of intents to purge
     */
    private void purgeIntents(Iterable<Intent> intents) {
        IntentService intentService = get(IntentService.class);
        this.purgeAfterRemove = true;
        removeIntentsByAppId(intentService, intents, null);
    }

    /**
     * Purges the intents passed as argument after confirmation is provided
     * for each of them.
     * If no explicit confirmation is provided, the intent is not purged.
     *
     * @param intents list of intents to purge
     */
    public void purgeIntentsInteractive(Iterable<Intent> intents) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        intents.forEach(intent -> {
            System.out.print(String.format("Id=%s, Key=%s, AppId=%s. Remove? [y/N]: ",
                                           intent.id(), intent.key(), intent.appId().name()));
            String response;
            try {
                response = br.readLine();
                response = response.trim().replace("\n", "");
                if ("y".equals(response)) {
                    this.purgeIntents(ImmutableList.of(intent));
                }
            } catch (IOException e) {
                response = "";
            }
            print(response);
        });
    }

    /**
     * Removes the intents passed as argument, assuming these
     * belong to the application's ID provided (if any) and
     * contain a key string.
     *
     * If an application ID is provided, it will be used to further
     * filter the intents to be removed.
     *
     * @param intents list of intents to remove
     * @param applicationIdString application ID to filter intents
     * @param keyString string to filter intents
     * @param purgeAfterRemove states whether the intents should be also purged
     * @param sync states whether the cli should wait for the operation to finish
     *             before returning
     */
    private void removeIntent(Iterable<Intent> intents,
                             String applicationIdString, String keyString,
                             boolean purgeAfterRemove, boolean sync) {
        IntentService intentService = get(IntentService.class);
        CoreService coreService = get(CoreService.class);
        this.applicationIdString = applicationIdString;
        this.keyString = keyString;
        this.purgeAfterRemove = purgeAfterRemove;
        this.sync = sync;
        if (purgeAfterRemove || sync) {
            print("Using \"sync\" to remove/purge intents - this may take a while...");
            print("Check \"summary\" to see remove/purge progress.");
        }

        ApplicationId appId = appId();
        if (!isNullOrEmpty(applicationIdString)) {
            appId = coreService.getAppId(applicationIdString);
            if (appId == null) {
                print("Cannot find application Id %s", applicationIdString);
                return;
            }
        }

        if (isNullOrEmpty(keyString)) {
            removeIntentsByAppId(intentService, intents, appId);

        } else {
            final Key key;
            if (keyString.startsWith("0x")) {
                // The intent uses a LongKey
                keyString = keyString.replaceFirst("0x", "");
                key = Key.of(new BigInteger(keyString, 16).longValue(), appId);
            } else {
                // The intent uses a StringKey
                key = Key.of(keyString, appId);
            }

            Intent intent = intentService.getIntent(key);
            if (intent != null) {
                removeIntent(intentService, intent);
            }
        }
    }

    /**
     * Removes the intents passed as argument.
     *
     * If an application ID is provided, it will be used to further
     * filter the intents to be removed.
     *
     * @param intentService IntentService object
     * @param intents intents to remove
     * @param appId application ID to filter intents
     */
    private void removeIntentsByAppId(IntentService intentService,
                                     Iterable<Intent> intents,
                                     ApplicationId appId) {
        for (Intent intent : intents) {
            if (appId == null || intent.appId().equals(appId)) {
                removeIntent(intentService, intent);
            }
        }
    }

    /**
     * Removes the intent passed as argument.
     *
     * @param intentService IntentService object
     * @param intent intent to remove
     */
    private void removeIntent(IntentService intentService, Intent intent) {
        IntentListener listener = null;
        Key key = intent.key();
        final CountDownLatch withdrawLatch, purgeLatch;
        if (purgeAfterRemove || sync) {
            // set up latch and listener to track uninstall progress
            withdrawLatch = new CountDownLatch(1);
            purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null;
            listener = (IntentEvent event) -> {
                if (Objects.equals(event.subject().key(), key)) {
                    if (event.type() == IntentEvent.Type.WITHDRAWN ||
                            event.type() == IntentEvent.Type.FAILED) {
                        withdrawLatch.countDown();
                    } else if (purgeLatch != null && purgeAfterRemove &&
                            event.type() == IntentEvent.Type.PURGED) {
                        purgeLatch.countDown();
                    }
                }
            };
            intentService.addListener(listener);
        } else {
            purgeLatch = null;
            withdrawLatch = null;
        }

        // request the withdraw
        intentService.withdraw(intent);

        if (withdrawLatch != null && (purgeAfterRemove || sync)) {
            try { // wait for withdraw event
                withdrawLatch.await(5, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                print("Timed out waiting for intent {} withdraw", key);
            }
            if (purgeLatch != null && purgeAfterRemove && CAN_PURGE.contains(intentService.getIntentState(key))) {
                intentService.purge(intent);
                if (sync) { // wait for purge event
                    /* TODO
                       Technically, the event comes before map.remove() is called.
                       If we depend on sync and purge working together, we will
                       need to address this.
                    */
                    try {
                        purgeLatch.await(5, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        print("Timed out waiting for intent {} purge", key);
                    }
                }
            }
        }

        if (listener != null) {
            // clean up the listener
            intentService.removeListener(listener);
        }
    }
}
