import {
  diffItems,
  noop,
  pCatch
} from '../utils'

// ===================================================================

// TODO: move into vm and rename to removeInterface
async function delete_ ({vif}) {
  this.allocIpAddresses(
    vif.id,
    vif.$network,
    null,
    vif.allowedIpv4Addresses.concat(vif.allowedIpv6Addresses)
  )::pCatch(noop)

  await this.getXapi(vif).deleteVif(vif._xapiId)
}
export {delete_ as delete}

delete_.params = {
  id: { type: 'string' }
}

delete_.resolve = {
  vif: ['id', 'VIF', 'administrate']
}

// -------------------------------------------------------------------

// TODO: move into vm and rename to disconnectInterface
export async function disconnect ({vif}) {
  // TODO: check if VIF is attached before
  await this.getXapi(vif).disconnectVif(vif._xapiId)
}

disconnect.params = {
  id: { type: 'string' }
}

disconnect.resolve = {
  vif: ['id', 'VIF', 'operate']
}

// -------------------------------------------------------------------
// TODO: move into vm and rename to connectInterface
export async function connect ({vif}) {
  // TODO: check if VIF is attached before
  await this.getXapi(vif).connectVif(vif._xapiId)
}

connect.params = {
  id: { type: 'string' }
}

connect.resolve = {
  vif: ['id', 'VIF', 'operate']
}

// -------------------------------------------------------------------

export async function set ({
  vif,
  network,
  mac,
  allowedIpv4Addresses,
  allowedIpv6Addresses,
  attached
}) {
  const oldIpAddresses = vif.allowedIpv4Addresses.concat(vif.allowedIpv6Addresses)
  const newIpAddresses = []
  {
    const { push } = newIpAddresses
    push.apply(newIpAddresses, allowedIpv4Addresses || vif.allowedIpv4Addresses)
    push.apply(newIpAddresses, allowedIpv6Addresses || vif.allowedIpv6Addresses)
  }

  if (network || mac) {
    const xapi = this.getXapi(vif)

    const vm = xapi.getObject(vif.$VM)
    mac == null && (mac = vif.MAC)
    network = xapi.getObject(network && network.id || vif.$network)
    attached == null && (attached = vif.attached)

    await this.allocIpAddresses(vif.id, null, oldIpAddresses)

    // create new VIF with new parameters
    await xapi.createVif(vm.$id, network.$id, {
      mac,
      currently_attached: attached,
      ipv4Allowed: allowedIpv4Addresses,
      ipv6Allowed: allowedIpv6Addresses
    })

    await this.allocIpAddresses(vif.id, newIpAddresses)

    return
  }

  const [ addAddresses, removeAddresses ] = diffItems(
    newIpAddresses,
    oldIpAddresses
  )
  await this.allocIpAddresses(
    vif.id,
    addAddresses,
    removeAddresses
  )

  return this.getXapi(vif).editVif(vif._xapiId, {
    ipv4Allowed: allowedIpv4Addresses,
    ipv6Allowed: allowedIpv6Addresses
  })
}

set.params = {
  id: { type: 'string' },
  network: { type: 'string', optional: true },
  mac: { type: 'string', optional: true },
  allowedIpv4Addresses: {
    type: 'array',
    items: {
      type: 'string'
    },
    optional: true
  },
  allowedIpv6Addresses: {
    type: 'array',
    items: {
      type: 'string'
    },
    optional: true
  },
  attached: { type: 'boolean', optional: true }
}

set.resolve = {
  vif: ['id', 'VIF', 'operate'],
  network: ['network', 'network', 'operate']
}

@@ -249,26 +249,8 @@
 id,%0A
-    vif.$network,%0A
     
@@ -2080,24 +2080,62 @@
 IpAddresses)
+%0A    await xapi.deleteVif(vif._xapiId)
 %0A%0A    // cre
@@ -2165,24 +2165,39 @@
 rameters%0A   
+ const newVif =
  await xapi.
@@ -2282,33 +2282,34 @@
 ,%0A      ipv4
-A
+_a
 llowed: 
 allowedIpv4A
@@ -2300,60 +2300,13 @@
 ed: 
-allowedIpv4Addresses,%0A      ipv6Allowed: allowedIpv6
+newIp
 Addr
@@ -2347,28 +2347,32 @@
 IpAddresses(
-v
+newV
 if.
+$
 id, newIpAdd

remove old VIF before creating new one (#457)