// 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 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 getVnet(String vmName) {
        return vmName.substring(vmName.lastIndexOf(SEPARATOR) + SEPARATOR.length());
    }
    
    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);
    }
}
