// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.test;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import com.cloud.network.Networks.TrafficType;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.net.NetUtils;

public class PodZoneConfig {
	
	public static void main(String[] args) {
		PodZoneConfig config = ComponentLocator.inject(PodZoneConfig.class);
		//config.run(args);
		System.exit(0);
    }
	
	public void savePod(boolean printOutput, long id, String name, long dcId, String gateway, String cidr, int vlanStart, int vlanEnd) {
		// Check that the cidr was valid
		if (!IPRangeConfig.validCIDR(cidr)) printError("Please enter a valid CIDR for pod: " + name);
		
		// Get the individual cidrAddress and cidrSize values
		String[] cidrPair = cidr.split("\\/");
		String cidrAddress = cidrPair[0];
		String cidrSize = cidrPair[1];

		String sql = null;
		if (id != -1) sql = "INSERT INTO `cloud`.`host_pod_ref` (id, name, data_center_id, gateway, cidr_address, cidr_size) " + "VALUES ('" + id + "','" + name + "','" + dcId + "','" + gateway + "','" + cidrAddress + "','" + cidrSize + "')";
		else sql = "INSERT INTO `cloud`.`host_pod_ref` (name, data_center_id, gateway, cidr_address, cidr_size) " + "VALUES ('" + name + "','" + dcId + "','" + gateway + "','" + cidrAddress + "','" + cidrSize + "')";
			
        DatabaseConfig.saveSQL(sql, "Failed to save pod due to exception. Please contact Cloud Support.");
        
        if (printOutput) System.out.println("Successfuly saved pod.");
	}
	
	public void checkAllPodCidrSubnets() {
		Vector<Long> allZoneIDs = getAllZoneIDs();
		for (Long dcId : allZoneIDs) {
			HashMap<Long, Vector<Object>> currentPodCidrSubnets = getCurrentPodCidrSubnets(dcId.longValue());
			String result = checkPodCidrSubnets(dcId.longValue(), currentPodCidrSubnets);
			if (!result.equals("success")) printError(result);
		}
	}
	
	private String checkPodCidrSubnets(long dcId, HashMap<Long, Vector<Object>> currentPodCidrSubnets) {
		
//		DataCenterDao _dcDao = null;
//        final ComponentLocator locator = ComponentLocator.getLocator("management-server");
        
//        _dcDao = locator.getDao(DataCenterDao.class);
		// For each pod, return an error if any of the following is true:
		// 1. The pod's CIDR subnet conflicts with the guest network subnet
		// 2. The pod's CIDR subnet conflicts with the CIDR subnet of any other pod
		
		String zoneName  = PodZoneConfig.getZoneName(dcId);
		
		//get the guest network cidr and guest netmask from the zone
//		DataCenterVO dcVo = _dcDao.findById(dcId);
		
		String guestNetworkCidr = IPRangeConfig.getGuestNetworkCidr(dcId);
		
		if (guestNetworkCidr == null || guestNetworkCidr.isEmpty()) return "Please specify a valid guest cidr";
        String[] cidrTuple = guestNetworkCidr.split("\\/");
        
		String guestIpNetwork = NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]));
		long guestCidrSize = Long.parseLong(cidrTuple[1]);
        
        // Iterate through all pods in this zone
		for (Long podId : currentPodCidrSubnets.keySet()) {
			String podName;
			if (podId.longValue() == -1) podName = "newPod";
			else podName = PodZoneConfig.getPodName(podId.longValue(), dcId);
			
			Vector<Object> cidrPair = currentPodCidrSubnets.get(podId);
			String cidrAddress = (String) cidrPair.get(0);
			long cidrSize = ((Long) cidrPair.get(1)).longValue();
			
			long cidrSizeToUse = -1;
			if (cidrSize < guestCidrSize) cidrSizeToUse = cidrSize;
			else cidrSizeToUse = guestCidrSize;
			
			String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSizeToUse);
			String guestSubnet = NetUtils.getCidrSubNet(guestIpNetwork, cidrSizeToUse);
			
			// Check that cidrSubnet does not equal guestSubnet
			if (cidrSubnet.equals(guestSubnet)) {
				if (podName.equals("newPod")) {
					return "The subnet of the pod you are adding conflicts with the subnet of the Guest IP Network. Please specify a different CIDR.";
				} else {
					return "Warning: The subnet of pod " + podName + " in zone " + zoneName + " conflicts with the subnet of the Guest IP Network. Please change either the pod's CIDR or the Guest IP Network's subnet, and re-run install-vmops-management.";
				}
			}
			
			// Iterate through the rest of the pods
			for (Long otherPodId : currentPodCidrSubnets.keySet()) {
				if (podId.equals(otherPodId)) continue;
				
				// Check that cidrSubnet does not equal otherCidrSubnet
				Vector<Object> otherCidrPair = currentPodCidrSubnets.get(otherPodId);
				String otherCidrAddress = (String) otherCidrPair.get(0);
				long otherCidrSize = ((Long) otherCidrPair.get(1)).longValue();
				
				if (cidrSize < otherCidrSize) cidrSizeToUse = cidrSize;
				else cidrSizeToUse = otherCidrSize;
				
				cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSizeToUse);
				String otherCidrSubnet = NetUtils.getCidrSubNet(otherCidrAddress, cidrSizeToUse);
				
				if (cidrSubnet.equals(otherCidrSubnet)) {
					String otherPodName = PodZoneConfig.getPodName(otherPodId.longValue(), dcId);
					if (podName.equals("newPod")) {
						return "The subnet of the pod you are adding conflicts with the subnet of pod " + otherPodName + " in zone " + zoneName + ". Please specify a different CIDR.";
					} else {
						return "Warning: The pods " + podName + " and " + otherPodName + " in zone " + zoneName + " have conflicting CIDR subnets. Please change the CIDR of one of these pods.";
					}
				}
			}
		}
		
		return "success";
	}
	
	@DB
	protected HashMap<Long, Vector<Object>> getCurrentPodCidrSubnets(long dcId) {
		HashMap<Long, Vector<Object>> currentPodCidrSubnets = new HashMap<Long, Vector<Object>>();
		
		String selectSql = "SELECT id, cidr_address, cidr_size FROM host_pod_ref WHERE data_center_id=" + dcId;
		Transaction txn = Transaction.currentTxn();
		try {
        	PreparedStatement stmt = txn.prepareAutoCloseStatement(selectSql);
        	ResultSet rs = stmt.executeQuery();
        	while (rs.next()) {
        		Long podId = rs.getLong("id");
        		String cidrAddress = rs.getString("cidr_address");
        		long cidrSize = rs.getLong("cidr_size");
        		Vector<Object> cidrPair = new Vector<Object>();
        		cidrPair.add(0, cidrAddress);
        		cidrPair.add(1, new Long(cidrSize));
        		currentPodCidrSubnets.put(podId, cidrPair);
        	}
        } catch (SQLException ex) {
        	System.out.println(ex.getMessage());
        	printError("There was an issue with reading currently saved pod CIDR subnets. Please contact Cloud Support.");
            return null;
        }
        
        return currentPodCidrSubnets;
	}
	
	public void deletePod(String name, long dcId) {
		String sql = "DELETE FROM `cloud`.`host_pod_ref` WHERE name=\"" + name + "\" AND data_center_id=\"" + dcId + "\"";
		DatabaseConfig.saveSQL(sql, "Failed to delete pod due to exception. Please contact Cloud Support.");
	}
	
	public long getVlanDbId(String zone, String vlanId) {
		long zoneId = getZoneId(zone);
		
		return DatabaseConfig.getDatabaseValueLong("SELECT * FROM `cloud`.`vlan` WHERE data_center_id=\"" + zoneId + "\" AND vlan_id =\"" + vlanId + "\"", "id",
		"Unable to start DB connection to read vlan DB id. Please contact Cloud Support.");
    }
	
	public List<String> modifyVlan(String zone, boolean add, String vlanId, String vlanGateway, String vlanNetmask, String pod, String vlanType, String ipRange, long networkId, long physicalNetworkId) {
    	// Check if the zone is valid
    	long zoneId = getZoneId(zone);
    	if (zoneId == -1)
    		return genReturnList("false", "Please specify a valid zone.");
    	
    	//check if physical network is valid
        long physicalNetworkDbId = checkPhysicalNetwork(physicalNetworkId);
        if (physicalNetworkId == -1)
            return genReturnList("false", "Please specify a valid physical network.");
    	
    	
    	Long podId = pod!=null?getPodId(pod, zone):null;
    	if (podId != null && podId == -1)
    		return genReturnList("false", "Please specify a valid pod.");
    	
    	if (add) {
    		
    		// Make sure the gateway is valid
    		if (!NetUtils.isValidIp(vlanGateway))
    			return genReturnList("false", "Please specify a valid gateway.");
    		
    		// Make sure the netmask is valid
    		if (!NetUtils.isValidIp(vlanNetmask))
    			return genReturnList("false", "Please specify a valid netmask.");
    		
    		// Check if a vlan with the same vlanId already exists in the specified zone
    		if (getVlanDbId(zone, vlanId) != -1)
    			return genReturnList("false", "A VLAN with the specified VLAN ID already exists in zone " + zone + ".");
    		
    		/*
    		// Check if another vlan in the same zone has the same subnet
    		String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask);
    		List<VlanVO> vlans = _vlanDao.findByZone(zoneId);
    		for (VlanVO vlan : vlans) {
    			String currentVlanSubnet = NetUtils.getSubNet(vlan.getVlanGateway(), vlan.getVlanNetmask());
    			if (newVlanSubnet.equals(currentVlanSubnet))
    				return genReturnList("false", "The VLAN with ID " + vlan.getVlanId() + " in zone " + zone + " has the same subnet. Please specify a different gateway/netmask.");
    		}
    		*/
    		
    		// Everything was fine, so persist the VLAN
    		saveVlan(zoneId, podId, vlanId, vlanGateway, vlanNetmask, vlanType, ipRange, networkId, physicalNetworkDbId);
            if (podId != null) {
            	long vlanDbId = getVlanDbId(zone, vlanId);
            	String sql = "INSERT INTO `cloud`.`pod_vlan_map` (pod_id, vlan_db_id) " + "VALUES ('" + podId + "','" + vlanDbId  + "')";
                DatabaseConfig.saveSQL(sql, "Failed to save pod_vlan_map due to exception vlanDbId=" + vlanDbId + ", podId=" + podId + ". Please contact Cloud Support.");
            }
    		
    		return genReturnList("true", "Successfully added VLAN.");
    		
    	} else {
    		return genReturnList("false", "That operation is not suppored.");
    	}
    	
    	/*
    	else {
    		
    		// Check if a VLAN actually exists in the specified zone
    		long vlanDbId = getVlanDbId(zone, vlanId);
    		if (vlanDbId == -1)
    			return genReturnList("false", "A VLAN with ID " + vlanId + " does not exist in zone " + zone);
    		
    		// Check if there are any public IPs that are in the specified vlan.
    		List<IPAddressVO> ips = _publicIpAddressDao.listByVlanDbId(vlanDbId);
    		if (ips.size() != 0)
    			return genReturnList("false", "Please delete all IP addresses that are in VLAN " + vlanId + " before deleting the VLAN.");
    		
    		// Delete the vlan
    		_vlanDao.delete(vlanDbId);
    		
    		return genReturnList("true", "Successfully deleted VLAN.");
    	}
    	*/
    }
	
	@DB
	public void saveZone(boolean printOutput, long id, String name, String dns1, String dns2, String dns3, String dns4, String guestNetworkCidr, String networkType) {
		
		if (printOutput) System.out.println("Saving zone, please wait...");
		
		String columns = null;
		String values = null;
		
		if (id != -1) {
			columns = "(id, name";
			values = "('" + id + "','" + name + "'";
		} else {
			columns = "(name";
			values = "('" + name + "'";
		}

		if (dns1 != null) {
			columns += ", dns1";
			values += ",'" + dns1 + "'";
		}
		
		if (dns2 != null) {
			columns += ", dns2";
			values += ",'" + dns2 + "'";
		}
		
		if (dns3 != null) {
			columns += ", internal_dns1";
			values += ",'" + dns3 + "'";
		}
		
		if (dns4 != null) {
			columns += ", internal_dns2";
			values += ",'" + dns4 + "'";
		}
		
		if(guestNetworkCidr != null) {
			columns += ", guest_network_cidr";
			values += ",'" + guestNetworkCidr + "'";
		}
		
		if(networkType != null) {
			columns += ", networktype";
			values += ",'" + networkType + "'";
		}
		
        columns += ", uuid";
        values += ", UUID()";
			
		columns += ")";
		values += ")";
		
		String sql = "INSERT INTO `cloud`.`data_center` " + columns +  " VALUES " + values;
		
		DatabaseConfig.saveSQL(sql, "Failed to save zone due to exception. Please contact Cloud Support.");
		
		if (printOutput) System.out.println("Successfully saved zone.");
	}
	
	@DB
    public void savePhysicalNetwork(boolean printOutput, long id, long dcId, int vnetStart, int vnetEnd) {
        
        if (printOutput) System.out.println("Saving physical network, please wait...");
        
        String columns = null;
        String values = null;
        
        columns = "(id ";
        values = "('" + id + "'";
        
        columns += ", name ";
        values += ",'physical network'";
        
        columns += ", data_center_id ";
        values += ",'" + dcId + "'";
        
        //save vnet information
        columns += ", vnet";
        values += ",'" + vnetStart + "-" + vnetEnd + "'";
            
        columns += ", state";
        values += ", 'Enabled'";
        
        columns += ", uuid";
        values += ", UUID()";
            
        columns += ")";
        values += ")";
        
        String sql = "INSERT INTO `cloud`.`physical_network` " + columns +  " VALUES " + values;
        
        DatabaseConfig.saveSQL(sql, "Failed to save physical network due to exception. Please contact Cloud Support.");
        
        // Hardcode the vnet range to be the full range
        int begin = 0x64;
        int end = 64000;
        
        // If vnet arguments were passed in, use them
        if (vnetStart != -1 && vnetEnd != -1) {
            begin = vnetStart;
            end = vnetEnd;
        }
        
        String insertVnet = "INSERT INTO `cloud`.`op_dc_vnet_alloc` (vnet, data_center_id, physical_network_id) VALUES ( ?, ?, ?)";

        Transaction txn = Transaction.currentTxn();
        try {
            PreparedStatement stmt = txn.prepareAutoCloseStatement(insertVnet);
            for (int i = begin; i <= end; i++) {
                stmt.setString(1, Integer.toString(i));
                stmt.setLong(2, dcId);
                stmt.setLong(3, id);
                stmt.addBatch();
            }
            stmt.executeBatch();
        } catch (SQLException ex) {
            printError("Error creating vnet for the physical network. Please contact Cloud Support.");
        }
        
        //add default traffic types
        
        //get default Xen network labels
        String defaultXenPrivateNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Management);
        String defaultXenPublicNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Public);
        String defaultXenStorageNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Storage);
        String defaultXenGuestNetworkLabel = getDefaultXenNetworkLabel(TrafficType.Guest);
        
        String insertTraficType = "INSERT INTO `cloud`.`physical_network_traffic_types` (physical_network_id, traffic_type, xen_network_label) VALUES ( ?, ?, ?)";

        try {
            PreparedStatement stmt = txn.prepareAutoCloseStatement(insertTraficType);
            for (TrafficType traffic : TrafficType.values()) {
                if(traffic.equals(TrafficType.Control) || traffic.equals(TrafficType.Vpn) ||
                        traffic.equals(TrafficType.None)){
                    continue;
                }
                stmt.setLong(1, id);
                stmt.setString(2, traffic.toString());
                if(traffic.equals(TrafficType.Public)){
                    stmt.setString(3, defaultXenPublicNetworkLabel);
                }else if(traffic.equals(TrafficType.Management)){
                    stmt.setString(3, defaultXenPrivateNetworkLabel);
                }else if(traffic.equals(TrafficType.Storage)){
                    stmt.setString(3, defaultXenStorageNetworkLabel);
                }else if(traffic.equals(TrafficType.Guest)){
                    stmt.setString(3, defaultXenGuestNetworkLabel);
                }
                
                stmt.addBatch();
            }
            stmt.executeBatch();
        } catch (SQLException ex) {
            printError("Error adding default traffic types for the physical network. Please contact Cloud Support.");
        }
        
        if (printOutput) System.out.println("Successfully saved physical network.");
    }
	
    private String getDefaultXenNetworkLabel(TrafficType trafficType){
        String xenLabel = null;
        String configName = null;
        switch(trafficType){
            case Public: configName = "xen.public.network.device";
            break;
            case Guest: configName = "xen.guest.network.device";
            break;
            case Storage: configName = "xen.storage.network.device1";
            break;
            case Management: configName = "xen.private.network.device";
            break;
        }
        
        if(configName != null){
            xenLabel = getConfiguredValue(configName);
        }
        return xenLabel;
    }
    
    public static String getConfiguredValue(String configName)
    {
        return DatabaseConfig.getDatabaseValueString("SELECT value FROM `cloud`.`configuration` where name = \"" + configName + "\"","value",
                "Unable to start DB connection to read configuration. Please contact Cloud Support.");
    }
	
	public void deleteZone(String name) {
		String sql = "DELETE FROM `cloud`.`data_center` WHERE name=\"" + name + "\"";
		DatabaseConfig.saveSQL(sql, "Failed to delete zone due to exception. Please contact Cloud Support.");
	}
	
	public void saveVlan(long zoneId, Long podId, String vlanId, String vlanGateway, String vlanNetmask, String vlanType, String ipRange, long networkId, long physicalNetworkId) {
		String sql = "INSERT INTO `cloud`.`vlan` (vlan_id, vlan_gateway, vlan_netmask, data_center_id, vlan_type, description, network_id, physical_network_id) " + "VALUES ('" + vlanId + "','" + vlanGateway + "','" + vlanNetmask + "','" + zoneId + "','" + vlanType + "','" + ipRange +  "','" + networkId +  "','" + physicalNetworkId + "')";
        DatabaseConfig.saveSQL(sql, "Failed to save vlan due to exception. Please contact Cloud Support.");
	}
	
	public static long getPodId(String pod, String zone) {
		long dcId = getZoneId(zone);
		String selectSql = "SELECT * FROM `cloud`.`host_pod_ref` WHERE name = \"" + pod + "\" AND data_center_id = \"" + dcId + "\"";
		String errorMsg = "Could not read pod ID fro mdatabase. Please contact Cloud Support.";
		return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
	}
	
	public static long getPodId(String pod, long dcId) {
        String selectSql = "SELECT * FROM `cloud`.`host_pod_ref` WHERE name = \"" + pod + "\" AND data_center_id = \"" + dcId + "\"";
        String errorMsg = "Could not read pod ID fro mdatabase. Please contact Cloud Support.";
        return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
    }
	
	public static long getZoneId(String zone) {
		String selectSql = "SELECT * FROM `cloud`.`data_center` WHERE name = \"" + zone + "\"";
		String errorMsg = "Could not read zone ID from database. Please contact Cloud Support.";
		return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
	}
	
    public static long checkPhysicalNetwork(long physicalNetworkId) {
        String selectSql = "SELECT * FROM `cloud`.`physical_network` WHERE id = \"" + physicalNetworkId + "\"";
        String errorMsg = "Could not read physicalNetwork ID from database. Please contact Cloud Support.";
        return DatabaseConfig.getDatabaseValueLong(selectSql, "id", errorMsg);
    }	
	
	@DB
	public Vector<Long> getAllZoneIDs() {
		Vector<Long> allZoneIDs = new Vector<Long>();
		
		String selectSql = "SELECT id FROM data_center";
		Transaction txn = Transaction.currentTxn();
		try {
        	PreparedStatement stmt = txn.prepareAutoCloseStatement(selectSql);
        	ResultSet rs = stmt.executeQuery();
        	while (rs.next()) {
        		Long dcId = rs.getLong("id");
        		allZoneIDs.add(dcId);
        	}
        } catch (SQLException ex) {
        	System.out.println(ex.getMessage());
        	printError("There was an issue with reading zone IDs. Please contact Cloud Support.");
            return null;
        }
        
        return allZoneIDs;
	}
	
	
	public static boolean validPod(String pod, String zone) {
		return (getPodId(pod, zone) != -1);
	}
	
	public static boolean validZone(String zone) {
		return (getZoneId(zone) != -1);
	}
	
	public static String getPodName(long podId, long dcId) {
		return DatabaseConfig.getDatabaseValueString("SELECT * FROM `cloud`.`host_pod_ref` WHERE id=" + podId + " AND data_center_id=" + dcId, "name",
		"Unable to start DB connection to read pod name. Please contact Cloud Support.");
	}
	
	public static String getZoneName(long dcId) {
		return DatabaseConfig.getDatabaseValueString("SELECT * FROM `cloud`.`data_center` WHERE id=" + dcId, "name",
		"Unable to start DB connection to read zone name. Please contact Cloud Support.");
	}
	
	private static void printError(String message) {
		DatabaseConfig.printError(message);
	}
	
	private List<String> genReturnList(String success, String message) {
    	List<String> returnList = new ArrayList<String>();
    	returnList.add(0, success);
    	returnList.add(1, message);
    	return returnList;
    }
	
}
