/*
 * Copyright 2014-present Open Networking Laboratory
 *
 * 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.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onlab.util.StringFilter;
import org.onlab.util.Tools;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.OpticalCircuitIntent;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalOduIntent;
import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;

import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.String.format;
import static org.apache.commons.lang3.text.WordUtils.uncapitalize;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * Lists the inventory of intents and their states.
 */
@Command(scope = "onos", name = "intents",
         description = "Lists the inventory of intents and their states")
public class IntentsListCommand extends AbstractShellCommand {

    // Color codes and style
    private static final String BOLD = "\u001B[1m";
    private static final String RESET = "\u001B[0m";

    // Messages and string formatter
    private static final String APP_ID = BOLD + "Application Id:" + RESET + " %s";

    private static final String COMMON_SELECTOR = BOLD + "Common ingress " +
            "selector:" + RESET + " %s";

    private static final String CP = BOLD + "Connect Point:" + RESET + " %s";

    private static final String CONSTRAINTS = BOLD + "Constraints:" + RESET + " %s";

    private static final String DST = BOLD + "Destination " + RESET;

    private static final String EGRESS = BOLD + "Egress ";

    private static final String FILTERED_CPS = "connect points and individual selectors" + RESET;

    private static final String HOST = "host:" + RESET + " %s";

    private static final String ID = BOLD + "Id:" + RESET + " %s";

    private static final String INHERITED = "Inherited";

    private static final String INGRESS = BOLD + "Ingress ";

    private static final String INDENTATION = " -> ";

    private static final String INSTALLABLE = BOLD + "Installable:" + RESET + " %s";

    private static final String KEY = BOLD + "Key:" + RESET + " %s";

    private static final String RESOURCES = BOLD + "Resources:" + RESET + " %s";

    private static final String SELECTOR = BOLD + "Selector:" + RESET + " %s";

    private static final String SEPARATOR = StringUtils.repeat("-", 172);

    private static final String SPACE = "   ";

    private static final String SRC = BOLD + "Source ";

    private static final String STATE = BOLD + "State:" + RESET + " %s";

    private static final String TREATMENT = BOLD + "Treatment:" + RESET + " %s";

    private static final String TYPE = BOLD + "Intent type:" + RESET + " %s";

    /**
     * {@value #SUMMARY_TITLES}.
     */
    private static final String SUMMARY_TITLES =
            BOLD + format(
            "\n%1s%21s%14s%14s%14s%14s%14s%14s%14s%14s%14s%14s",
            "Intent type",
            "Total",
            "Installed",
            "Withdrawn",
            "Failed",
            "InstallReq",
            "Compiling",
            "Installing",
            "Recompiling",
            "WithdrawReq",
            "Withdrawing",
            "UnknownState") +
            RESET;

    @Option(name = "-i", aliases = "--installable",
            description = "Output Installable Intents",
            required = false, multiValued = false)
    private boolean showInstallable = false;

    @Option(name = "-s", aliases = "--summary",
            description = "Intents summary",
            required = false, multiValued = false)
    private boolean intentsSummary = false;

    @Option(name = "-m", aliases = "--mini-summary",
            description = "Intents mini summary",
            required = false, multiValued = false)
    private boolean miniSummary = false;

    @Option(name = "-p", aliases = "--pending",
            description = "Show information about pending intents",
            required = false, multiValued = false)
    private boolean pending = false;

    @Option(name = "-f", aliases = "--filter",
            description = "Filter intents by specific keyword",
            required = false, multiValued = true)
    private List<String> filter = new ArrayList<>();

    private StringFilter contentFilter;
    private IntentService service;

    @Override
    protected void execute() {
        service = get(IntentService.class);
        contentFilter = new StringFilter(filter, StringFilter.Strategy.AND);

        Iterable<Intent> intents;
        if (pending) {
            intents = service.getPending();
        } else {
            intents = service.getIntents();
        }

        if (intentsSummary || miniSummary) {
            Map<String, IntentSummary> summarized = summarize(intents);
            if (outputJson()) {
                ObjectNode summaries = mapper().createObjectNode();
                summarized.forEach((n, s) -> summaries.set(uncapitalize(n), s.json(mapper())));
                print("%s", summaries);
            } else if (miniSummary) {
                StringBuilder builder = new StringBuilder();
                builder.append(summarized.remove("All").miniSummary());
                summarized.values().forEach(s -> builder.append(s.miniSummary()));
                print("%s", builder.toString());
            } else {
                StringBuilder builder = new StringBuilder();
                builder.append(SUMMARY_TITLES);
                builder.append('\n').append(SEPARATOR);
                builder.append(summarized.remove("All").summary());
                summarized.values().forEach(s -> builder.append(s.summary()));
                print("%s", builder.toString());
            }
            return;
        }

        if (outputJson()) {
            print("%s", json(intents));
        } else {
            for (Intent intent : intents) {
                IntentState state = service.getIntentState(intent.key());
                StringBuilder intentFormat = fullFormat(intent, state);
                StringBuilder detailsIntentFormat = detailsFormat(intent, state);
                String formatted = intentFormat.append(detailsIntentFormat).toString();
                if (contentFilter.filter(formatted)) {
                    print("%s\n", formatted);
                }
            }
        }
    }

    /**
     * Internal local class to keep track of a single type Intent summary.
     */
    private class IntentSummary {
        private final String intentType;
        private int total = 0;
        private int installReq = 0;
        private int compiling = 0;
        private int installing = 0;
        private int installed = 0;
        private int recompiling = 0;
        private int withdrawReq = 0;
        private int withdrawing = 0;
        private int withdrawn = 0;
        private int failed = 0;
        private int unknownState = 0;

        /**
         * Creates empty {@link IntentSummary} for specified {@code intentType}.
         *
         * @param intentType the string describing the Intent type
         */
        IntentSummary(String intentType) {
            this.intentType = intentType;
        }

        /**
         * Creates {@link IntentSummary} initialized with given {@code intent}.
         *
         * @param intent to initialize with
         */
        IntentSummary(Intent intent) {
            // remove "Intent" from intentType label
            this(intentType(intent));
            update(service.getIntentState(intent.key()));
        }

        // for identity element, when reducing
        IntentSummary() {
            this.intentType = null;
        }

        /**
         * Updates the Intent Summary.
         *
         * @param intentState the state of the intent
         */
        void update(IntentState intentState) {
            total++;
            switch (intentState) {
            case INSTALL_REQ:
                installReq++;
                break;
            case COMPILING:
                compiling++;
                break;
            case INSTALLING:
                installing++;
                break;
            case INSTALLED:
                installed++;
                break;
            case RECOMPILING:
                recompiling++;
                break;
            case WITHDRAW_REQ:
                withdrawReq++;
                break;
            case WITHDRAWING:
                withdrawing++;
                break;
            case WITHDRAWN:
                withdrawn++;
                break;
            case FAILED:
                failed++;
                break;
            default:
                unknownState++;
                break;
            }
        }

        /**
         * Prints the Intent Summary.
         *
         */
        StringBuilder summary() {
            StringBuilder builder = new StringBuilder();

            builder.append(format(
                    "\n%1s%s%14d%14d%14d%14d%14d%14d%14d%14d%14d%14d",
                    BOLD + intentType + RESET,
                    Strings.padStart(String.valueOf(total),
                                     (32 - intentType.length()),
                                     ' '),
                    installed,
                    withdrawn,
                    failed,
                    installReq,
                    compiling,
                    installing,
                    recompiling,
                    withdrawReq,
                    withdrawing,
                    unknownState));
            builder.append('\n').append(SEPARATOR);

            return builder;
        }

        StringBuilder miniSummary() {
            StringBuilder builder = new StringBuilder();
            builder.append(BOLD).append(intentType).append(RESET)
                    .append(" (").append(total).append(')').append('\n');
            builder.append('\t')
                   .append("installed: ").append(installed).append(' ')
                   .append("withdrawn: ").append(withdrawn).append(' ')
                   .append("failed: ").append(failed)
                   .append('\n');
            builder.append('\t')
                   .append("compiling: ").append(compiling).append(' ')
                   .append("installing: ").append(installing).append(' ')
                   .append("recompiling: ").append(recompiling).append(' ')
                   .append("withdrawing: ").append(withdrawing)
                   .append('\n');
            builder.append('\t')
                   .append("installReq: ").append(installReq).append(' ')
                   .append("withdrawReq: ").append(withdrawReq).append(' ')
                   .append("unknownState: ").append(unknownState)
                   .append('\n')
                   .append('\n');
            return builder;
        }

        /**
         * Gets the JSON representation of the Intent Summary.
         *
         * @param mapper the object mapper
         * @return the JSON representation of the Intent Summary
         */
        JsonNode json(ObjectMapper mapper) {
            ObjectNode result = mapper.createObjectNode()
                .put("total", total)
                .put("installed", installed)
                .put("failed", failed)
                .put("installReq", installReq)
                .put("installing", installing)
                .put("compiling", compiling)
                .put("recompiling", recompiling)
                .put("withdrawReq", withdrawReq)
                .put("withdrawing", withdrawing)
                .put("withdrawn", withdrawn)
                .put("unknownState", unknownState);

            return result;
        }
    }

    /**
     * Merges 2 {@link IntentSummary} together.
     *
     * @param a element to merge
     * @param b element to merge
     * @return merged {@link IntentSummary}
     */
    IntentSummary merge(IntentSummary a, IntentSummary b) {
        IntentSummary m = new IntentSummary(firstNonNull(a.intentType, b.intentType));
        m.total         = a.total + b.total;
        m.installReq    = a.installReq + b.installReq;
        m.compiling     = a.compiling + b.compiling;
        m.installing    = a.installing + b.installing;
        m.installed     = a.installed + b.installed;
        m.recompiling   = a.recompiling + b.recompiling;
        m.withdrawing   = a.withdrawing + b.withdrawing;
        m.withdrawReq   = a.withdrawReq + b.withdrawReq;
        m.withdrawn     = a.withdrawn + b.withdrawn;
        m.failed        = a.failed + b.failed;
        m.unknownState  = a.unknownState + b.unknownState;
        return m;
    }

    /**
     * Returns IntentType string.
     *
     * @param intent input
     * @return IntentType string
     */
    private static String intentType(Intent intent) {
        return intent.getClass().getSimpleName().replace("Intent", "");
    }

    /**
     * Build summary of intents per intent type.
     *
     * @param intents to summarize
     * @return summaries per Intent type
     */
    private Map<String, IntentSummary> summarize(Iterable<Intent> intents) {
        Map<String, List<Intent>> perIntent = Tools.stream(intents)
            .collect(Collectors.groupingBy(i -> intentType(i)));

        List<IntentSummary> collect = perIntent.values().stream()
            .map(il ->
                il.stream()
                    .map(IntentSummary::new)
                    .reduce(new IntentSummary(), this::merge)
            ).collect(Collectors.toList());

        Map<String, IntentSummary> summaries = new HashMap<>();

        // individual
        collect.forEach(is -> summaries.put(is.intentType, is));

        // all summarised
        summaries.put("All", collect.stream()
                              .reduce(new IntentSummary("All"), this::merge));
        return summaries;
    }

    /**
     * Returns detailed information text about a specific intent.
     *
     * @param intent to print
     * @param state of intent
     * @return detailed information or "" if {@code state} was null
     */
    private StringBuilder detailsFormat(Intent intent, IntentState state) {
        StringBuilder builder = new StringBuilder();
        if (state == null) {
            return builder;
        }
        if (!intent.resources().isEmpty()) {
            builder.append('\n').append(format(RESOURCES, intent.resources()));
        }
        if (intent instanceof ConnectivityIntent) {
            ConnectivityIntent ci = (ConnectivityIntent) intent;
            if (!ci.selector().criteria().isEmpty()) {
                builder.append('\n').append(format(COMMON_SELECTOR, formatSelector(ci.selector())));
            }
            if (!ci.treatment().allInstructions().isEmpty()) {
                builder.append('\n').append(format(TREATMENT, ci.treatment().allInstructions()));
            }
            if (ci.constraints() != null && !ci.constraints().isEmpty()) {
                builder.append('\n').append(format(CONSTRAINTS, ci.constraints()));
            }
        }

        if (intent instanceof HostToHostIntent) {
            HostToHostIntent pi = (HostToHostIntent) intent;
            builder.append('\n').append(format(SRC + HOST, pi.one()));
            builder.append('\n').append(format(DST + HOST, pi.two()));
        } else if (intent instanceof PointToPointIntent) {
            PointToPointIntent pi = (PointToPointIntent) intent;
            builder.append('\n').append(formatFilteredCps(Sets.newHashSet(pi.filteredIngressPoint()), INGRESS));
            builder.append('\n').append(formatFilteredCps(Sets.newHashSet(pi.filteredEgressPoint()), EGRESS));
        } else if (intent instanceof MultiPointToSinglePointIntent) {
            MultiPointToSinglePointIntent pi = (MultiPointToSinglePointIntent) intent;
            builder.append('\n').append(formatFilteredCps(pi.filteredIngressPoints(), INGRESS));
            builder.append('\n').append(formatFilteredCps(Sets.newHashSet(pi.filteredEgressPoint()), EGRESS));
        } else if (intent instanceof SinglePointToMultiPointIntent) {
            SinglePointToMultiPointIntent pi = (SinglePointToMultiPointIntent) intent;
            builder.append('\n').append(formatFilteredCps(Sets.newHashSet(pi.filteredIngressPoint()), INGRESS));
            builder.append('\n').append(formatFilteredCps(pi.filteredEgressPoints(), EGRESS));
        } else if (intent instanceof PathIntent) {
            PathIntent pi = (PathIntent) intent;
            builder.append(format("path=%s, cost=%f", pi.path().links(), pi.path().cost()));
        } else if (intent instanceof LinkCollectionIntent) {
            LinkCollectionIntent li = (LinkCollectionIntent) intent;
            builder.append('\n').append(format("links=%s", li.links()));
            builder.append('\n').append(format(CP, li.egressPoints()));
        } else if (intent instanceof OpticalCircuitIntent) {
            OpticalCircuitIntent ci = (OpticalCircuitIntent) intent;
            builder.append('\n').append(format("src=%s, dst=%s", ci.getSrc(), ci.getDst()));
        } else if (intent instanceof OpticalConnectivityIntent) {
            OpticalConnectivityIntent ci = (OpticalConnectivityIntent) intent;
            builder.append('\n').append(format("src=%s, dst=%s", ci.getSrc(), ci.getDst()));
        } else if (intent instanceof OpticalOduIntent) {
            OpticalOduIntent ci = (OpticalOduIntent) intent;
            builder.append('\n').append(format("src=%s, dst=%s", ci.getSrc(), ci.getDst()));
        }

        List<Intent> installable = service.getInstallableIntents(intent.key());
        installable.stream().filter(i -> contentFilter.filter(i));
        if (showInstallable && installable != null && !installable.isEmpty()) {
            builder.append('\n').append(format(INSTALLABLE, installable));
        }
        return builder;
    }

    /*
     * Prints out a formatted string, given a list of connect points.
     */
    private StringBuilder formatFilteredCps(Set<FilteredConnectPoint> fCps, String prefix) {
        StringBuilder builder = new StringBuilder();
        builder.append(prefix);
        builder.append(FILTERED_CPS);
        fCps.forEach(fCp -> builder.append('\n').append(formatFilteredCp(fCp)));

        return builder;
    }

    /*
     * Prints out a formatted string, given a filtered connect point.
     */
    private StringBuilder formatFilteredCp(FilteredConnectPoint fCp) {
        ConnectPoint connectPoint = fCp.connectPoint();
        TrafficSelector selector = fCp.trafficSelector();
        StringBuilder builder = new StringBuilder();
        builder.append(INDENTATION).append(format(CP, connectPoint));
        builder.append(SPACE).append(format(SELECTOR, formatSelector(selector)));

        return builder;
    }

    /*
     * Prints out a formatted string, given a traffic selector
     */
    private StringBuilder formatSelector(TrafficSelector ts) {
        StringBuilder builder = new StringBuilder();
        List<Criterion> criteria = Lists.newArrayList(ts.criteria());

        if (criteria == null || criteria.isEmpty()) {
            builder.append(INHERITED);
            return builder;
        }

        criteria.forEach(c -> {
            builder.append(c.toString());
            if (criteria.indexOf(c) < criteria.size() - 1) {
                builder.append(", ");
            }
        });

        return builder;
    }

    /*
     * Prints information about the intent state, given an intent.
     */
    private StringBuilder fullFormat(Intent intent, IntentState state) {
        StringBuilder builder = new StringBuilder();
        builder.append(format(ID, intent.id()));
        if (state != null) {
            builder.append('\n').append(format(STATE, state));
        }
        builder.append('\n').append(format(KEY, intent.key()));
        builder.append('\n').append(format(TYPE, intent.getClass().getSimpleName()));
        builder.append('\n').append(format(APP_ID, intent.appId().name()));

        return builder;
    }

    /*
     * Produces a JSON array from the intents specified.
     */
    private JsonNode json(Iterable<Intent> intents) {
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode result = mapper.createArrayNode();
        StreamSupport.stream(intents.spliterator(), false)
                .filter(intent -> contentFilter.filter(jsonForEntity(intent, Intent.class).toString()))
                .forEach(intent -> result.add(jsonForEntity(intent, Intent.class)));
        return result;
    }

}
