# frozen_string_literal: true

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

module Litany
  class ECS < BaseService
    child_resource ECSCluster, :cluster

    property :cluster_size, 2, Integer
    property :instance_type, 'm4.large', [String]
    property :trusted_services, ['ec2.amazonaws.com', 'ecs.amazonaws.com'], Array
    property :root_volume_size, 8, Integer

    resource_collection ECSScheduledTask, :scheduled_task, required: false
    resource_collection ECSService, :service, required: false
    resource_collection IAMRole, :role, required: false

    resource_reference Image, :image, required: false

    validator(:cluster) do
      raise "You must set `image` unless `cluster_size` is set to zero." if image.nil? && cluster_size.positive?

      if cluster_size.zero?
        raise 'You may not set `image` if `cluster_size` is set to zero.' if set_image?
        raise 'You may not set `instance_type` if `cluster_size` is set to zero.' if set_instance_type?
        raise 'You may not set `instance_group`, `instance``, nor configure `launch_configuration`` or `auto_scaling_group` settings if `cluster_size` is set to zero.' if set_instances? || set_instance_groups?
      end
    end

    def auto_scaling_group(&block)
      instance_group(name).auto_scaling_group(&block) # TODO: v2 change to "#{name}_ecs"
    end

    def launch_configuration(&block)
      instance_group(name).launch_configuration(&block) # TODO: v2 change to "#{name}_ecs"
    end

    def finalize_resource
      super
      return if cluster_size.zero?

      if ArcanaSupport.automatic?
        key = kms_key(service_id)
        key.allow role: :instance_profile
        key.allow role: ArcanaSupport.instance.admin_role

        instance_profile.allow 's3:GetObject', join([ref(ArcanaSupport.instance.bucket, :Arn), service_id, '*'], '/')
      end

      instance_group(name).group_size(cluster_size) unless instance_group(name).set_group_size?

      meta :ecs_cluster_name, cluster.name

      instance_actions = [
        'ecs:DeregisterContainerInstance', 'ecs:DiscoverPollEndpoint', 'ecs:Poll', 'ecs:RegisterContainerInstance', 'ecs:StartTelemetrySession',
        'ecs:Submit*', 'ecr:GetAuthorizationToken', 'ecr:BatchCheckLayerAvailability', 'ecr:GetDownloadUrlForLayer', 'ecr:BatchGetImage', 'logs:CreateLogStream', 'logs:PutLogEvents'
      ]

      instance_profile.allow instance_actions, '*'

      # Referencing security group
      to_lbs_sg.description "Used to reference instances of the #{name} ECS Cluster."
      launch_configuration.security_group to_lbs_sg

      # Set Block Device Mapping sizes
      instance_group(name).device_prefix 'xvd' # For Amazon Linux Only, use default 'sd' on Ubuntu
      instance_group(name).root_volume_size root_volume_size
    end

    def to_lbs_sg
      security_group :"#{name}_ecs_to_albs" # Leaving albs here for comparability reasons.
    end

    alias_method :reference_sg, :to_lbs_sg

    def default_tags
      {
        LitanyECSName: self.name
      }
    end
  end
end
