/*
 * Copyright 2015-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.vpls.cli;

import com.google.common.collect.Lists;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.net.EncapsulationType;
import org.onosproject.vpls.config.VplsConfigService;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static com.google.common.base.Strings.isNullOrEmpty;

/**
 * CLI to interact with the VPLS application.
 */
@Command(scope = "onos", name = "vpls",
        description = "Manages the VPLS application")
public class VplsCommand extends AbstractShellCommand {

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

    // Messages and string formatter
    private static final String ENCAP_NOT_FOUND =
            COLOR_ERROR + "Encapsulation type " + BOLD + "%s" + RESET +
                    COLOR_ERROR + " not found" + RESET;

    private static final String IFACE_NOT_FOUND =
            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " not found" + RESET;

    private static final String IFACE_ALREADY_ASSOCIATED =
            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " already associated to VPLS " + BOLD + "%s" + RESET +
                    COLOR_ERROR + "" + RESET;

    private static final String INSERT_VPLS_NAME =
            COLOR_ERROR + "Missing the " + BOLD + "VPLS name." + RESET +
                    COLOR_ERROR + " Specifying a VPLS name is mandatory." +
                    RESET;

    private static final String INSERT_ENCAP_TYPE =
            COLOR_ERROR + "Missing the " + BOLD + "encapsulation type." +
                    RESET + COLOR_ERROR + " Encapsulation type is mandatory." +
                    RESET;

    private static final String INSERT_INTERFACE =
            COLOR_ERROR + "Missing the " + BOLD + "interface name." +
                    RESET + COLOR_ERROR + " Specifying an interface name is" +
                    " mandatory." + RESET;

    private static final String SEPARATOR = "----------------";

    private static final String VPLS_ALREADY_EXISTS =
            COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " already exists" + RESET;

    private static final String VPLS_COMMAND_NOT_FOUND =
            COLOR_ERROR + "VPLS command " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " not found" + RESET;

    private static final String VPLS_DISPLAY = "VPLS name: " + BOLD +
            "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s";

    private static final String VPLS_NOT_FOUND =
            COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " not found" + RESET;

    private static final String IFACE_NOT_ASSOCIATED =
            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
                    " cannot be removed from VPLS " + BOLD + "%s" + RESET +
                    COLOR_ERROR + ". The interface is associated to another" +
                    "VPLS (" + BOLD + "%s" + RESET + COLOR_ERROR + ")" + RESET;

    private static VplsConfigService vplsConfigService =
            get(VplsConfigService.class);

    @Argument(index = 0, name = "command", description = "Command name (add-if|" +
            "clean|create|delete|list|rem-if|set-encap|show)",
            required = true, multiValued = false)
    String command = null;

    @Argument(index = 1, name = "vplsName", description = "The name of the VPLS",
            required = false, multiValued = false)
    String vplsName = null;

    @Argument(index = 2, name = "optArg", description = "The interface name or" +
            " the encapsulation type for set-encap",
            required = false, multiValued = false)
    String optArg = null;

    @Override
    protected void execute() {
        VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
        if (enumCommand != null) {
            switch (enumCommand) {
                case ADD_IFACE:
                    addIface(vplsName, optArg);
                    break;
                case CLEAN:
                    clean();
                    break;
                case CREATE:
                    create(vplsName);
                    break;
                case DELETE:
                    delete(vplsName);
                    break;
                case LIST:
                    list();
                    break;
                case REMOVE_IFACE:
                    removeIface(vplsName, optArg);
                    break;
                case SET_ENCAP:
                    setEncap(vplsName, optArg);
                    break;
                case SHOW:
                    show(vplsName);
                    break;
                default:
                    print(VPLS_COMMAND_NOT_FOUND, command);
            }
        } else {
            print(VPLS_COMMAND_NOT_FOUND, command);
        }
    }

    /**
     * Adds an inteterface to a VPLS.
     *
     * @param vplsName the name of the VLPS
     * @param ifaceName the name of the interface to add
     */
    private void addIface(String vplsName, String ifaceName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (ifaceName == null) {
            print(INSERT_INTERFACE);
            return;
        }
        if (!vplsExists(vplsName)) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        if (!ifaceExists(ifaceName)) {
            print(IFACE_NOT_FOUND, ifaceName);
            return;
        }
        if (isIfaceAssociated(ifaceName)) {
            print(IFACE_ALREADY_ASSOCIATED,
                  ifaceName, vplsNameFromIfaceName(ifaceName));
            return;
        }

        vplsConfigService.addIface(vplsName, ifaceName);
    }

    /**
     * Cleans the VPLS configuration.
     */
    private void clean() {
        vplsConfigService.cleanVplsConfig();
    }

    /**
     * Creates a new VPLS.
     *
     * @param vplsName the name of the VLPS
     */
    private void create(String vplsName) {
        if (vplsName == null || vplsName.isEmpty()) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (vplsExists(vplsName)) {
            print(VPLS_ALREADY_EXISTS, vplsName);
            return;
        }
        vplsConfigService.addVpls(vplsName, Sets.newHashSet(), null);
    }

    /**
     * Deletes a VPLS.
     *
     * @param vplsName the name of the VLPS
     */
    private void delete(String vplsName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (!vplsExists(vplsName)) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        vplsConfigService.removeVpls(vplsName);
    }

    /**
     * Lists the configured VPLSs.
     */
    private void list() {
        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
        Collections.sort(vplsNames);

        vplsNames.forEach(vpls -> {
            print(vpls);
        });
    }

    /**
     * Removes an interface from a VPLS.
     *
     * @param vplsName the name of the VLPS
     * @param ifaceName the name of the interface to remove
     */
    private void removeIface(String vplsName, String ifaceName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (ifaceName == null) {
            print(INSERT_INTERFACE);
            return;
        }
        if (!vplsExists(vplsName)) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        if (!ifaceExists(ifaceName)) {
            print(IFACE_NOT_FOUND, ifaceName);
            return;
        }
        String vplsNameFromIfaceName = vplsNameFromIfaceName(ifaceName);
        if (!vplsNameFromIfaceName.equals(vplsName)) {
            print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName, vplsNameFromIfaceName);
            return;
        }
        vplsConfigService.removeIface(ifaceName);
    }

    /**
     * Sets the encapsulation type for a VPLS.
     *
     * @param vplsName the name of the VPLS
     * @param encap the encapsulation type
     */
    private void setEncap(String vplsName, String encap) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (encap == null) {
            print(INSERT_ENCAP_TYPE);
            return;
        }
        if (!vplsExists(vplsName)) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        EncapsulationType encapType = EncapsulationType.enumFromString(encap);
        if (encapType.equals(EncapsulationType.NONE) &&
            !encapType.toString().equals(encap)) {
            print(ENCAP_NOT_FOUND, encap);
            return;
        }
        vplsConfigService.setEncap(vplsName, encap);
    }

    /**
     * Shows the details of one or more VPLSs.
     *
     * @param vplsName the name of the VPLS
     */
    private void show(String vplsName) {
        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
        Collections.sort(vplsNames);

        Map<String, EncapsulationType> encapByVplsName =
                vplsConfigService.encapByVplsName();

        if (!isNullOrEmpty(vplsName)) {
            // A VPLS name is provided. Check first if the VPLS exists
            if (vplsExists(vplsName)) {
                print(VPLS_DISPLAY,
                      vplsName,
                      ifacesFromVplsName(vplsName).toString(),
                      encapByVplsName.get(vplsName).toString());
            } else {
                print(VPLS_NOT_FOUND, vplsName);
            }
        } else {
            // No VPLS names are provided. Display all VPLSs configured
            print(SEPARATOR);
            vplsNames.forEach(v -> {
                print(VPLS_DISPLAY,
                      v,
                      ifacesFromVplsName(v).toString(),
                      encapByVplsName.get(v).toString());
                print(SEPARATOR);
            });
        }
    }

    /**
     * States if a VPLS exists or not.
     *
     * @param vplsName the name of the VPLS
     * @return true if the VPLS exists; false otherwise
     */
    private static boolean vplsExists(String vplsName) {
        return vplsConfigService.vplsNames().contains(vplsName);
    }

    /**
     * States if an interface is defined or not in the system.
     *
     * @param ifaceName the name of the interface
     * @return true if the interface is defined; false otherwise
     */
    private static boolean ifaceExists(String ifaceName) {
        return vplsConfigService.allIfaces()
                .stream()
                .anyMatch(iface -> iface.name().equals(ifaceName));
    }

    /**
     * States if an interface is already associated to a VPLS.
     *
     * @param ifaceName the name of the interface
     * @return true if the interface is already associated to a VPLS; false
     * otherwise
     */
    private static boolean isIfaceAssociated(String ifaceName) {
        return vplsConfigService.ifaces()
                .stream()
                .anyMatch(iface -> iface.name().equals(ifaceName));
    }

    /**
     * Returns the name of a VPLS, given the name of an interface associated to
     * it.
     *
     * @param ifaceName the name of the interface
     * @return the name of the VPLS that has the interface configured; null if
     * the interface does not exist or is not associated to any VPLS
     */
    private static String vplsNameFromIfaceName(String ifaceName) {
        String vplsName = null;

        Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
                .entries()
                .stream()
                .filter((entry -> entry.getValue().name().equals(ifaceName)))
                .map(Map.Entry::getKey)
                .findFirst();

        if (optVplsName.isPresent()) {
            vplsName = optVplsName.get();
        }

        return vplsName;
    }

    /**
     * Returns a list of interfaces associated to a VPLS, given a VPLS name.
     *
     * @param vplsName the name of the VPLS
     * @return the set of interfaces associated to the given VPLS; null if the
     * VPLS is not found
     */
    private static Set<String> ifacesFromVplsName(String vplsName) {
        if (!vplsExists(vplsName)) {
            return null;
        }
        SetMultimap<String, Interface> ifacesByVplsName =
                vplsConfigService.ifacesByVplsName();
        Set<String> ifaceNames = Sets.newHashSet();

        ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));

        return ifaceNames;
    }
}
