#  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
    res: io.murano.resources
    sys: io.murano.system

Name: Environment

Properties:
  name:
    Contract: $.string().notNull()

  applications:
    Contract: [$.class(Application).owned().notNull()]

  agentListener:
    Contract: $.class(sys:AgentListener)
    Usage: Runtime

  stack:
    Contract: $.class(sys:HeatStack)
    Usage: Runtime

  instanceNotifier:
    Contract: $.class(sys:InstanceNotifier)
    Usage: Runtime

  defaultNetworks:
    Contract:
      environment: $.template(res:Network)
      flat: $.template(res:Network)

  securityGroupManager:
    Contract: $.class(sys:SecurityGroupManager)
    Usage: Runtime

  reporter:
    Contract: $.class(sys:StatusReporter)
    Usage: Runtime

  regionConfigs:
    Contract:
      $.string():
        agentRabbitMq:
          host: $.string().notNull()
          port: $.int() or 5672
          login: $.string().notNull()
          password: $.string().notNull()
          virtual_host: $.string() or '/'
          ssl: $.bool() or false
          insecure: $.bool() or false
    Usage: Config

  region:
    Contract: $.string()
    Usage: InOut

  homeRegionName:
    Contract: $.string()
    Usage: Runtime

  regions:
    Contract:
      $.string(): $.class(CloudRegion)
    Usage: InOut


Methods:
  .init:
    Body:
      - $.homeRegionName: config(home_region) or ''
      - $._assignRegions()
      - $.instanceNotifier: new(sys:InstanceNotifier, environment => $this)
      - $.reporter: new(sys:StatusReporter, environment => $this)
      - $.regions: $.regions + $.regionConfigs.keys().
          where($ and not $this.regions.containsKey($)).
          select($this._createRegion($)).
          toDict($.name)
      - If: not $.regions.containsKey('')
        Then:
        - If: $.homeRegionName
          Then:
            $.regions['']: $.regions[$.homeRegionName]
          Else:
            $.regions['']: $._createRegion('')

      - $defaultRegion: $.regions['']
      - $.stack: $defaultRegion.stack
      - $.securityGroupManager: $defaultRegion.securityGroupManager

  _createRegion:
    Arguments:
      regionName:
        Contract: $.string()
    Body:
      - $envNet: $.defaultNetworks.environment?.set(regionName => $regionName)
      - $flatNet: $.defaultNetworks.flat?.set(regionName => $regionName)
      - Return: new(CloudRegion, $this,
            name => $regionName,
            defaultNetworks => {
                environment => $envNet,
                flat => $flatNet
              }
          )

  deploy:
    Scope: Public
    Body:
      - $.applications.pselect($.deploy())

  _assignRegions:
    Body:
      - If: $.region = null
        Then:
          $.region: $.homeRegionName

      - $defaultRegionConfig:
          agentRabbitMq:
            host: config(rabbitmq, host)
            port: config(rabbitmq, port)
            login: config(rabbitmq, login)
            password: config(rabbitmq, password)
            virtual_host: config(rabbitmq, virtual_host)
            ssl: config(rabbitmq, ssl)

      - If: not $.regionConfigs.containsKey('')
        Then:
        - $.regionConfigs: $.regionConfigs.set('' => $defaultRegionConfig)

      - If: $.homeRegionName and not $.regionConfigs.containsKey($.homeRegionName)
        Then:
        - $.regionConfigs: $.regionConfigs.set($.homeRegionName => $defaultRegionConfig)
