// 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.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.ComponentContext;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.net.NetUtils;

public class PodZoneConfig {

    public static void main(String[] args) {
        PodZoneConfig config = ComponentContext.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("Successfully 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;
        TransactionLegacy txn = TransactionLegacy.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.isValidIp4(vlanGateway))
                return genReturnList("false", "Please specify a valid gateway.");

            // Make sure the netmask is valid
            if (!NetUtils.isValidIp4(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 (?,?)";
                String errorMsg =  "Failed to save pod_vlan_map due to exception vlanDbId=" + vlanDbId + ", podId=" + podId + ". Please contact Cloud Support.";
                TransactionLegacy txn = TransactionLegacy.open("saveSQL");
                try ( PreparedStatement stmt = txn.prepareAutoCloseStatement(sql); ) {
                        stmt.setString(1, podId.toString());
                        stmt.setString(2, String.valueOf(vlanDbId));
                        stmt.executeUpdate();
                    } catch (SQLException ex) {
                        System.out.println("SQL Exception: " + ex.getMessage());
                        printError(errorMsg);
                    }
            }

            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 ( ?, ?, ?)";

        TransactionLegacy txn = TransactionLegacy.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, xenserver_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 = "xenserver.public.network.device";
                break;
            case Guest:
                configName = "xenserver.guest.network.device";
                break;
            case Storage:
                configName = "xenserver.storage.network.device1";
                break;
            case Management:
                configName = "xenserver.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, ip4_range, 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";
        TransactionLegacy txn = TransactionLegacy.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;
    }

}
