// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 com.cloud.vm;

import java.util.Formatter;

import com.cloud.dc.Vlan;

/**
 * VM Name.
 */
public class VirtualMachineName {
    public static final String SEPARATOR = "-";

    public static boolean isValidCloudStackVmName(String name, String instance) {
        String[] parts = name.split(SEPARATOR);
        if (parts.length <= 1) {
            return false;
        }

        if (!parts[parts.length - 1].equals(instance)) {
            return false;
        }

        return true;
    }

    public static String getVnetName(long vnetId) {
        StringBuilder vnet = new StringBuilder();
        Formatter formatter = new Formatter(vnet);
        formatter.format("%04x", vnetId);
        return vnet.toString();
    }

    public static boolean isValidVmName(String vmName) {
        return isValidVmName(vmName, null);
    }

    public static boolean isValidVmName(String vmName, String instance) {
        String[] tokens = vmName.split(SEPARATOR);
        /*Some vms doesn't have vlan/vnet id*/
        if (tokens.length != 5 && tokens.length != 4) {
            return false;
        }

        if (!tokens[0].equals("i")) {
            return false;
        }

        try {
            Long.parseLong(tokens[1]);
            Long.parseLong(tokens[2]);
            if (tokens.length == 5 && !Vlan.UNTAGGED.equalsIgnoreCase(tokens[4])) {
                Long.parseLong(tokens[4], 16);
            }
        } catch (NumberFormatException e) {
            return false;
        }

        return instance == null || instance.equals(tokens[3]);
    }

    public static String getVmName(long vmId, long userId, String instance) {
        StringBuilder vmName = new StringBuilder("i");
        vmName.append(SEPARATOR).append(userId).append(SEPARATOR).append(vmId);
        vmName.append(SEPARATOR).append(instance);
        return vmName.toString();
    }

    public static long getVmId(String vmName) {
        int begin = vmName.indexOf(SEPARATOR);
        begin = vmName.indexOf(SEPARATOR, begin + SEPARATOR.length());
        int end = vmName.indexOf(SEPARATOR, begin + SEPARATOR.length());
        return Long.parseLong(vmName.substring(begin + 1, end));
    }

    public static long getRouterId(String routerName) {
        int begin = routerName.indexOf(SEPARATOR);
        int end = routerName.indexOf(SEPARATOR, begin + SEPARATOR.length());
        return Long.parseLong(routerName.substring(begin + 1, end));
    }

    public static long getConsoleProxyId(String vmName) {
        int begin = vmName.indexOf(SEPARATOR);
        int end = vmName.indexOf(SEPARATOR, begin + SEPARATOR.length());
        return Long.parseLong(vmName.substring(begin + 1, end));
    }

    public static long getSystemVmId(String vmName) {
        int begin = vmName.indexOf(SEPARATOR);
        int end = vmName.indexOf(SEPARATOR, begin + SEPARATOR.length());
        return Long.parseLong(vmName.substring(begin + 1, end));
    }

    public static String getRouterName(long routerId, String instance) {
        StringBuilder builder = new StringBuilder("r");
        builder.append(SEPARATOR).append(routerId).append(SEPARATOR).append(instance);
        return builder.toString();
    }

    public static String getConsoleProxyName(long vmId, String instance) {
        StringBuilder builder = new StringBuilder("v");
        builder.append(SEPARATOR).append(vmId).append(SEPARATOR).append(instance);
        return builder.toString();
    }

    public static String getSystemVmName(long vmId, String instance, String prefix) {
        StringBuilder builder = new StringBuilder(prefix);
        builder.append(SEPARATOR).append(vmId).append(SEPARATOR).append(instance);
        return builder.toString();
    }

    public static String attachVnet(String name, String vnet) {
        return name + SEPARATOR + vnet;
    }

    public static boolean isValidRouterName(String name) {
        return isValidRouterName(name, null);
    }

    public static boolean isValidRouterName(String name, String instance) {
        String[] tokens = name.split(SEPARATOR);
        if (tokens.length != 3 && tokens.length != 4) {
            return false;
        }

        if (!tokens[0].equals("r")) {
            return false;
        }

        try {
            Long.parseLong(tokens[1]);
        } catch (NumberFormatException ex) {
            return false;
        }

        return instance == null || tokens[2].equals(instance);
    }

    public static boolean isValidConsoleProxyName(String name) {
        return isValidConsoleProxyName(name, null);
    }

    public static boolean isValidConsoleProxyName(String name, String instance) {
        String[] tokens = name.split(SEPARATOR);
        if (tokens.length != 3) {
            return false;
        }

        if (!tokens[0].equals("v")) {
            return false;
        }

        try {
            Long.parseLong(tokens[1]);
        } catch (NumberFormatException ex) {
            return false;
        }

        return instance == null || tokens[2].equals(instance);
    }

    public static boolean isValidSecStorageVmName(String name, String instance) {
        return isValidSystemVmName(name, instance, "s");
    }

    public static boolean isValidSystemVmName(String name, String instance, String prefix) {
        String[] tokens = name.split(SEPARATOR);
        if (tokens.length != 3) {
            return false;
        }

        if (!tokens[0].equals(prefix)) {
            return false;
        }

        try {
            Long.parseLong(tokens[1]);
        } catch (NumberFormatException ex) {
            return false;
        }

        return instance == null || tokens[2].equals(instance);
    }
}
