#  Licensed 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.

Namespaces:
  =: io.murano.resources
  std: io.murano
  sys: io.murano.system

Name: ExistingNeutronNetwork

Extends: NeutronNetworkBase

Properties:
  internalNetworkName:
    Contract: $.string()
    Default: null
    Usage: InOut

  internalSubnetworkName:
    Contract: $.string()
    Default: null
    Usage: InOut

  externalNetworkName:
    Contract: $.string()
    Default: null
    Usage: InOut

Workflow:
  initialize:
    Body:
      - $environment: $.find(std:Environment).require()
      - $._netExplorer: new(sys:NetworkExplorer, $environment)
      - $._networks: null
      - $._subnetworks: null
      - $._ports: null
      - $._internalNetworkId: null
      - $._internalSubnetworkId: null
      - $._externalNetworkId: null

  deploy:
    Body:
      - If: $.internalNetworkName = null
        Then:
          $.internalNetworkName: $._getNetworks().where(
             $.get('router:external') = false).first().name

      - If: $._internalNetworkId = null
        Then:
          $._internalNetworkId: $._getNetworks().where(
            $.name = $this.internalNetworkName or
            $.id = $this.internalNetworkName).first().id

      - If: $.internalSubnetworkName = null
        Then:
          $.internalSubnetworkName: $._getSubnetworks().where(
            $.network_id = $this._internalNetworkId).first().name
      - If: $._internalSubnetworkId = null
        Then:
          $._internalSubnetworkId: $._getSubnetworks().where(
            ($.name = $this.internalSubnetworkName or
              $.id = $this.internalSubnetworkName) and
                $.network_id = $this._internalNetworkId).first().id

      - If: $.externalNetworkName = null and $._internalNetworkId != null
        Then:
          - $ports: $._netExplorer.listPorts()
          - $routerCandidates: $ports.where(
              $.network_id = $this._internalNetworkId and $.device_owner = 'network:router_interface').
              select($.device_id)
          - $networkCandidates: $ports.where(
              $.device_id in $routerCandidates and $.network_id != $this._internalNetworkId).
              select($.network_id)
          - $externalNetwork: $._getNetworks().where(
              $.get('router:external') = true and $.id in $networkCandidates).
              firstOrDefault()
          - If: $externalNetwork != null
            Then:
              - $.externalNetworkName: $externalNetwork.name
              - $._externalNetworkId: $externalNetwork.id

      - If: $.externalNetworkName = null
        Then:
          $.externalNetworkName: $._getNetworks().where(
            $.get('router:external') = true).select($.name).firstOrDefault()
      - If: $._externalNetworkId = null and $.externalNetworkName != null
        Then:
          $._externalNetworkId: $._getNetworks().where(
            $.name = $this.externalNetworkName or
            $.id = $this.externalNetworkName).first().id

  _getNetworks:
    Body:
      - If: $._networks = null
        Then:
          $._networks: $._netExplorer.listNetworks()
      - Return: $._networks

  _getSubnetworks:
    Body:
      - If: $._subnetworks = null
        Then:
          $._subnetworks : $._netExplorer.listSubnetworks()
      - Return: $._subnetworks

  joinInstance:
    Arguments:
      - instance:
          Contract: $.class(Instance).notNull()
      - securityGroupName:
          Contract: $.string()
      - assignFloatingIp:
          Contract: $.bool().notNull()
      - sharedIps:
          Contract:
            - $.class(std:SharedIp)
    Body:
      - $.deploy()
      - $fipName: null
      - $floatingIpNetRef: null
      - If: $assignFloatingIp
        Then:
          - $floatingIpNetRef: $._externalNetworkId
          - $fipName: format('fip-{0}-{1}', $.id(), $instance.name)

      - Return: $.joinInstanceToNetwork(
            instance => $instance,
            securityGroupName => $securityGroupName,
            sharedIps => $sharedIps,
            netRef => $._internalNetworkId,
            subnetRef => $._internalSubnetworkId,
            floatingIpResourceName => $fipName,
            floatingIpNetRef => $floatingIpNetRef
          )

  describe:
    Body:
      - $.deploy()
      - $subnet: $._getSubnetworks.where(
            $.network_id = $this._internalNetworkId).first()
      - Return:
          provider: Neutron
          netId: $._internalNetworkId
          netName: $.internalNetworkName
          subnetId: $._internalSubnetworkId
          cidr: $subnet.cidr
          dns: $subnet.dns_nameservers
          gateway: $subnet.gateway_ip
          floatingIpNetId: $._externalNetworkId
