/*
 * 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 static Vpls vpls;
    protected static 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 static 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);
    }
}
