# frozen_string_literal: true

require 'litany/mixins'
require 'litany/resource'

module Litany
  class ElasticFileSystem < Resource
    include Stack
    include Taggable

    cfn_type 'AWS::EFS::FileSystem'
    tag_key :FileSystemTags

    property :mode, :general_purpose, [:general_purpose, :max_io]
    flag :encrypted, true

    resource_collection EFSMountTarget, :mount_target
    resource_collection SecurityGroup, :security_group

    resource_reference KMSKey, :encryption_key, required: false
    resource_reference VPC, :vpc, inherited: true

    resource_references Environment, :only_in, required: false

    validator(:encryption) do
      raise 'If setting `encryption_key` you must set `encrypted` to true.' if set_encryption_key? && !encrypted
    end

    def access_sg
      security_group :"#{name}_efs_access"
    end

    def allow(source: nil, beanstalk: nil, environment: nil, ecs: nil)
      configs = [source.nil?, beanstalk.nil?, ecs.nil?]

      raise 'You must provide either a `source`, ecs cluster, or beanstalk environment.' if configs.count(true) == 3
      raise 'You may only provide one `source`, ecs cluster, or a beanstalk environment in the same `ingress` call.' unless configs.count(false) == 1
      raise 'You must specify both `beanstalk` and `environment` to allow ingress from a beanstalk environment' if !beanstalk.nil? && environment.nil?

      access_sg.ingress port: 2049, source: Beanstalk.new(beanstalk).beanstalk_environment(environment).reference_sg unless beanstalk.nil?
      deferred { access_sg.ingress port: 2049, source: ECSService.new(ecs).reference_sg } unless ecs.nil?
      access_sg.ingress port: 2049, source: source unless source.nil?
    end

    def finalize_resource
      vpc.subnets.each do |subnet|
        target = mount_target :"#{name}_#{subnet.name}"
        target.subnet subnet
        target.access_sg access_sg
      end

      access_sg.description 'Allows connectivity to this EFS Filesystem'
    end

    def properties
      props = {
        Encrypted: encrypted?,
        PerformanceMode: mode.camel_case
      }

      props[:KmsKeyId] = ref(encryption_key) if set_encryption_key?

      props
    end
  end
end
