<#
.Synopsis
   Short description
.DESCRIPTION
   Long description
.EXAMPLE
   Example of how to use this cmdlet
.EXAMPLE
   Another example of how to use this cmdlet
#>
function Get-ITDIbDNSRecord {
    [CmdletBinding()]
    Param
    (
        [string[]]
        $Hostname,

        [PSCredential]
        $Credential
    )

    Begin {
        If (!($Credential)) {
            $Credential = Get-Credential
        }
    }
    Process {
        $result = @()
        ForEach ($h in $hostname) {
            $x = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host?name=$h" -ContentType "application/json" -Credential $Credential
            If ($x) {
                $obj = [PSCustomObject]@{
                    'HostName'    = $x.ipv4addrs.Host;
                    'IPv4Address' = $x.ipv4addrs.ipv4addr
                    'DHCP'        = $x.ipv4addrs.configure_for_dhcp
                }
                $result += $obj
            }
        }
    }
    End {
        Write-Output $result
    }
}

<#
.Synopsis
   Short description
.DESCRIPTION
   Long description
.EXAMPLE
   Example of how to use this cmdlet
.EXAMPLE
   Another example of how to use this cmdlet
#>
function New-ITDIbDNSRecord {
    [CmdletBinding()]
    Param
    (
        [ipaddress]
        $IPv4Address,

        [string]
        $Hostname,

        [PSCredential]
        $Credential
    )

    Begin {
        If (!($Credential)) {
            $Credential = Get-Credential
        }

        $Uri = "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host"
        $IPs = @([PSCustomObject]@{'ipv4addr' = $IPv4Address })
    }
    Process {
        $obj = [PSCustomObject]@{
            'ipv4addrs' = $IPs;
            'name'      = $Hostname;
            'view'      = "default";
        }
        $postJson = $obj | ConvertTo-Json
        Invoke-RestMethod -Uri $Uri -Method Post -Body $postJson -ContentType "application/json" -Credential $Credential
    }
    End {
    }
}

function Get-IPs { 
 
    Param
    ( 
        [Parameter(Mandatory = $true)] 
        [array]
        $Subnets 
    ) 

    foreach ($subnet in $subnets) { 
        
        #Split IP and subnet 
        $IP = ($Subnet -split "\/")[0] 
        $SubnetBits = ($Subnet -split "\/")[1] 
        
        #Convert IP into binary 
        #Split IP into different octects and for each one, figure out the binary with leading zeros and add to the total 
        $Octets = $IP -split "\." 
        $IPInBinary = @() 
        foreach ($Octet in $Octets) { 
            #convert to binary 
            $OctetInBinary = [convert]::ToString($Octet, 2) 
            
            #get length of binary string add leading zeros to make octet 
            $OctetInBinary = ("0" * (8 - ($OctetInBinary).Length) + $OctetInBinary) 

            $IPInBinary = $IPInBinary + $OctetInBinary 
        } 
        $IPInBinary = $IPInBinary -join "" 

        #Get network ID by subtracting subnet mask 
        $HostBits = 32 - $SubnetBits 
        $NetworkIDInBinary = $IPInBinary.Substring(0, $SubnetBits) 
        
        #Get host ID and get the first host ID by converting all 1s into 0s 
        $HostIDInBinary = $IPInBinary.Substring($SubnetBits, $HostBits)         
        $HostIDInBinary = $HostIDInBinary -replace "1", "0" 

        #Work out all the host IDs in that subnet by cycling through $i from 1 up to max $HostIDInBinary (i.e. 1s stringed up to $HostBits) 
        #Work out max $HostIDInBinary 
        $imax = [convert]::ToInt32(("1" * $HostBits), 2) - 1 

        $IPs = @() 

        #Next ID is first network ID converted to decimal plus $i then converted to binary 
        For ($i = 1 ; $i -le $imax ; $i++) { 
            #Convert to decimal and add $i 
            $NextHostIDInDecimal = ([convert]::ToInt32($HostIDInBinary, 2) + $i) 
            #Convert back to binary 
            $NextHostIDInBinary = [convert]::ToString($NextHostIDInDecimal, 2) 
            #Add leading zeros 
            #Number of zeros to add  
            $NoOfZerosToAdd = $HostIDInBinary.Length - $NextHostIDInBinary.Length 
            $NextHostIDInBinary = ("0" * $NoOfZerosToAdd) + $NextHostIDInBinary 

            #Work out next IP 
            #Add networkID to hostID 
            $NextIPInBinary = $NetworkIDInBinary + $NextHostIDInBinary 
            #Split into octets and separate by . then join 
            $IP = @() 
            For ($x = 1 ; $x -le 4 ; $x++) { 
                #Work out start character position 
                $StartCharNumber = ($x - 1) * 8 
                #Get octet in binary 
                $IPOctetInBinary = $NextIPInBinary.Substring($StartCharNumber, 8) 
                #Convert octet into decimal 
                $IPOctetInDecimal = [convert]::ToInt32($IPOctetInBinary, 2) 
                #Add octet to IP  
                $IP += $IPOctetInDecimal 
            } 

            #Separate by . 
            $IP = $IP -join "." 
            $IPs += $IP 

                
        } 
        $IPs 
    }
}

<#
.SYNOPSIS
    Dynamically creates DNS A records
.DESCRIPTION
    Dynamically creates DNS A records based on CIDR input
.EXAMPLE
    New-ITDIbDNSRecordNextAvailableIP -Hostname itdserver1.nd.gov -CIDR 10.11.12.0/23 -Credential $Credential
.EXAMPLE
    New-ITDIbDNSRecordNextAvailableIP -Hostname itdserver2.nd.gov,itdserver3.nd.gov,itdserver4.nd.gov -CIDR 10.11.12.0/23 -Credential $Credential
.INPUTS
    Inputs to this cmdlet (if any)
.OUTPUTS
    Output from this cmdlet (if any)
.NOTES
    General notes
.COMPONENT
    The component this cmdlet belongs to
.ROLE
    The role this cmdlet belongs to
.FUNCTIONALITY
    The functionality that best describes this cmdlet
#>
function New-ITDIbDNSRecordNextAvailableIP {
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Hostname,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [ValidatePattern("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))$")]
        [string]
        $CIDR,

        [PSCredential]
        $Credential
    )
    
    begin {
        $NetworkAddress = $CIDR.split('/')[0]
        $IPs = Get-IPs -Subnets $CIDR
        $ExcludeIPs = $IPs | select -First 1
    }
    
    process {
        #$ curl -k -u admin:infoblox -X GET https://10.64.41.6/wapi/v1.1/network?ipv4addr=10.144.2.0
        try {
            $networkobj = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/network?ipv4addr=$NetworkAddress" -Credential $Credential -ContentType "application/json" -ErrorAction Stop
            $networkobjref = $networkobj._ref
    
            #curl -k -u admin:infoblox -X POST https://10.64.41.6/wapi/v1.1/network/ZG5zLm5ldHdvcmskMTAuMTQ0LjIuMC8yNC8w:10.144.2.0/24/default?_function=next_available_ip -H "Content-Type: application/json" -d '{"exclude": ["10.144.2.8", "10.144.2.10"], "num": 6}'
            $bodyjson = @{num = @($Hostname).count; exclude = @($ExcludeIPs) } | ConvertTo-Json
            #Invoke-RestMethod -Method Post -Uri ("https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $networkobjref + "?_function=next_available_ip") -ContentType "application/json"  -Credential $Credential -Body '{"exclude": ["10.11.12.1", "10.11.12.2"], "num": 6}'  #WORKS
            $IPsAvailable = (Invoke-RestMethod -Method Post -Uri ("https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $networkobjref + "?_function=next_available_ip") -ContentType "application/json"  -Credential $Credential -Body $bodyjson -ErrorAction Stop).Ips
            
            $IPCount = 0
    
            ForEach ($hn in $hostname) {
                if (Get-ITDIbDNSRecord -Hostname $hn -Credential $Credential) {
                    Write-Warning "DNS record already exists"
                }
                else {
                    New-ITDIbDNSRecord -IPv4Address $IPsAvailable[$IPCount] -Hostname $hn -Credential $Credential   -ErrorAction Stop
                    $IPcount++
                }
            }    
        }
        catch [System.Net.WebException] {
            Write-Error "webexception error"
        }        
    }
    
    end {
    }
}

function Get-ITDIbVlan {
    [CmdletBinding()]
    Param(
        [Parameter(
            ParameterSetName = 'VlanLookup')]
        [ValidateRange(0, 4096)]
        [int[]]
        $Vlan,

        [Parameter(
            ParameterSetName = 'CIDRLookup')]
        [string[]]
        $CIDR,

        [PSCredential]
        $Credential
    )
    begin {

    }
    process {        
        $Output = @()

        switch ($PsCmdlet.ParameterSetName) {
            "VlanLookup" {
                ForEach ($v in $Vlan) {
                    $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?id=$v&_return_as_object=1&_return_fields=assigned_to,id,name,parent,comment,description"  -ContentType "application/json" -Credential $Credential
                    $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } }
                    $Output += $InvokePSObject
                }
            }
            "CIDRLookup" {
                ForEach ($c in $CIDR) {
                    $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?_return_as_object=1&_max_results=-50000&_return_fields=assigned_to,id,name,parent,comment,description" -ContentType "application/json" -Credential $Credential
                    $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } }
                    $Output += $InvokePSObject | Where-Object AssignedTo -EQ $c
                }
            }
            "default" {
                $InvokeResult = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.11.3/vlan?_return_as_object=1&_max_results=-50000&_return_fields=assigned_to,id,name,parent,comment,description" -ContentType "application/json" -Credential $Credential
                $InvokePSObject = $InvokeResult.result | Select-Object id, Name, Comment, @{n = "AssignedTo"; e = { $_.Assigned_to.split(':')[1] -replace '/default' } }
                $Output = $InvokePSObject
            }
        }
    }
    end {
        Write-Output $Output 
    }
}

function Remove-ITDIbDnsRecord {
    [CmdletBinding()]
    param (
        [string]
        $ComputerName,

        [PSCredential]
        $Credential
    )
    
    Begin {
        If (!($Credential)) {
            $Credential = Get-Credential
        }

        
    }
    Process {
        $DNSRecord = Invoke-RestMethod -Method Get -Uri "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/record:host?name=$ComputerName" -ContentType "application/json" -Credential $Credential
        $UriToDelete = ( "https://infoblox-gmv.ns.nd.gov/wapi/v2.7/" + $DNSRecord._ref )
        Invoke-RestMethod -Method Delete -Uri $UriToDelete -ContentType "application/json" -Credential $Credential
    }
    
    end {
        
    }
}








