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

import com.google.common.collect.ImmutableSet;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.net.EncapsulationType;
import org.onosproject.vpls.api.VplsData;
import org.onosproject.vpls.api.Vpls;
import org.onosproject.vpls.api.VplsData.VplsState;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onosproject.vpls.api.VplsData.VplsState.*;


/**
 * CLI to interact with the VPLS application.
 */
@Command(scope = "onos", name = "vpls",
        description = "Manages the VPLS application")
public class VplsCommand extends AbstractShellCommand {
    private static final Set<VplsState> CHANGING_STATE =
            ImmutableSet.of(ADDING, REMOVING, UPDATING);

    // 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\n" +
            "State: %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 + ".";

    protected Vpls vpls;
    protected InterfaceService interfaceService;

    @Argument(index = 0, name = "command", description = "Command name (add-if|" +
            "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() {
        if (vpls == null) {
            vpls = get(Vpls.class);
        }
        if (interfaceService == null) {
            interfaceService = get(InterfaceService.class);
        }

        VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
        if (enumCommand != null) {
            switch (enumCommand) {
                case ADD_IFACE:
                    addIface(vplsName, optArg);
                    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;
                case CLEAN:
                    cleanVpls();
                    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
     */
    protected void addIface(String vplsName, String ifaceName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (ifaceName == null) {
            print(INSERT_INTERFACE);
            return;
        }

        Interface iface = getInterface(ifaceName);
        VplsData vplsData = vpls.getVpls(vplsName);

        if (vplsData == null) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        if (CHANGING_STATE.contains(vplsData.state())) {
            // when a VPLS is updating, we shouldn't try modify it.
            print("VPLS %s still updating, please wait it finished", vplsData.name());
            return;
        }
        if (iface == null) {
            print(IFACE_NOT_FOUND, ifaceName);
            return;
        }
        if (isIfaceAssociated(iface)) {
            print(IFACE_ALREADY_ASSOCIATED,
                  ifaceName, getVplsByInterface(iface).name());
            return;
        }
        vpls.addInterface(vplsData, iface);
    }

    /**
     * Creates a new VPLS.
     *
     * @param vplsName the name of the VLPS
     */
    protected void create(String vplsName) {
        if (vplsName == null || vplsName.isEmpty()) {
            print(INSERT_VPLS_NAME);
            return;
        }
        VplsData vplsData = vpls.getVpls(vplsName);
        if (vplsData != null) {
            print(VPLS_ALREADY_EXISTS, vplsName);
            return;
        }
        vpls.createVpls(vplsName, EncapsulationType.NONE);
    }

    /**
     * Deletes a VPLS.
     *
     * @param vplsName the name of the VLPS
     */
    protected void delete(String vplsName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        VplsData vplsData = vpls.getVpls(vplsName);
        if (vplsData == null) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        if (CHANGING_STATE.contains(vplsData.state())) {
            // when a VPLS is updating, we shouldn't try modify it.
            print("VPLS %s still updating, please wait it finished", vplsData.name());
            return;
        }
        vpls.removeVpls(vplsData);
    }

    /**
     * Lists the configured VPLSs.
     */
    protected void list() {
        List<String> vplsNames = vpls.getAllVpls().stream()
                .map(VplsData::name)
                .collect(Collectors.toList());
        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
     */
    protected void removeIface(String vplsName, String ifaceName) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (ifaceName == null) {
            print(INSERT_INTERFACE);
            return;
        }
        VplsData vplsData = vpls.getVpls(vplsName);
        Interface iface = getInterface(ifaceName);
        if (vplsData == null) {
            print(VPLS_NOT_FOUND, vplsName);
            return;
        }
        if (CHANGING_STATE.contains(vplsData.state())) {
            // when a VPLS is updating, we shouldn't try modify it.
            print("VPLS %s still updating, please wait it finished", vplsData.name());
            return;
        }
        if (iface == null) {
            print(IFACE_NOT_FOUND, ifaceName);
            return;
        }
        if (!vplsData.interfaces().contains(iface)) {
            print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName);
            return;
        }
        vpls.removeInterface(vplsData, iface);
    }

    /**
     * Sets the encapsulation type for a VPLS.
     *
     * @param vplsName the name of the VPLS
     * @param encap the encapsulation type
     */
    protected void setEncap(String vplsName, String encap) {
        if (vplsName == null) {
            print(INSERT_VPLS_NAME);
            return;
        }
        if (encap == null) {
            print(INSERT_ENCAP_TYPE);
            return;
        }
        VplsData vplsData = vpls.getVpls(vplsName);
        if (vplsData == null) {
            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;
        }
        vpls.setEncapsulationType(vplsData, encapType);
    }

    /**
     * Shows the details of one or more VPLSs.
     *
     * @param vplsName the name of the VPLS
     */
    protected void show(String vplsName) {
        if (!isNullOrEmpty(vplsName)) {
            // A VPLS name is provided. Check first if the VPLS exists
            VplsData vplsData = vpls.getVpls(vplsName);
            if (vplsData != null) {
                Set<String> ifaceNames = vplsData.interfaces().stream()
                        .map(Interface::name)
                        .collect(Collectors.toSet());
                print(VPLS_DISPLAY,
                      vplsName,
                      ifaceNames,
                      vplsData.encapsulationType().toString(),
                      vplsData.state());
            } else {
                print(VPLS_NOT_FOUND, vplsName);
            }
        } else {
            Collection<VplsData> vplses = vpls.getAllVpls();
            // No VPLS names are provided. Display all VPLSs configured
            print(SEPARATOR);
            vplses.forEach(vplsData -> {
                Set<String> ifaceNames = vplsData.interfaces().stream()
                        .map(Interface::name)
                        .collect(Collectors.toSet());
                print(VPLS_DISPLAY,
                      vplsData.name(),
                      ifaceNames,
                      vplsData.encapsulationType().toString(),
                      vplsData.state());
                print(SEPARATOR);
            });
        }
    }

    /**
     * Remove all VPLS.
     */
    protected void cleanVpls() {
        vpls.removeAllVpls();
    }


    /**
     * States if an interface is already associated to a VPLS.
     *
     * @param iface the interface
     * @return true if the interface is already associated to a VPLS; false
     * otherwise
     */
    private boolean isIfaceAssociated(Interface iface) {
        return vpls.getAllVpls()
                .stream()
                .map(VplsData::interfaces)
                .flatMap(Collection::stream)
                .anyMatch(iface::equals);
    }

    /**
     * Gets a network interface by given interface name.
     *
     * @param interfaceName the interface name
     * @return the network interface
     */
    private Interface getInterface(String interfaceName) {
        // FIXME: only returns first interface it found
        // multiple interface with same name not support
        return interfaceService.getInterfaces().stream()
                .filter(iface -> iface.name().equals(interfaceName))
                .findFirst()
                .orElse(null);
    }

    /**
     * Gets a VPLS related to the network interface.
     *
     * @param iface the network interface
     * @return the VPLS related to the network interface
     */
    private VplsData getVplsByInterface(Interface iface) {
        return vpls.getAllVpls().stream()
                .filter(vplsData -> vplsData.interfaces().contains(iface))
                .findFirst()
                .orElse(null);
    }
}
