# frozen_string_literal: true

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

module Litany
  class ElasticLoadBalancer < Resource
    include Taggable

    cfn_type 'AWS::ElasticLoadBalancing::LoadBalancer'
    parent_resource :service

    flag :internal, false, inherited: true

    property :connection_drain_seconds, false, [false, 1..300], inherited: true
    property :cross_zone, true, [true, false], inherited: true
    property :idle_timeout, 10, 1..120, inherited: true

    property :health_up_threshold, 3, [2..100], inherited: true
    property :health_down_threshold, 2, [2..100], inherited: true
    property :health_interval, 5, [5..100], inherited: true
    property :health_timeout, 2, [2..100], inherited: true
    property :health_protocol, :http, [:http, :https, :tcp, :ssl], inherited: true
    property :health_port, 2, [1..65535], inherited: true
    property :health_path, '/', [nil, String], inherited: true

    resource_collection CloudWatchAlarm, :cloudwatch_alarm, required: false
    resource_collection DNSAlias, :dns_alias, required: false
    resource_collection ElasticLoadBalancerListener, :listener, required: false

    resource_references Instance, :instance, required: false
    resource_references SecurityGroup, :security_group

    def add_listener(name, listener_port:, listener_protocol: :http, instance_port:, instance_protocol: :http, certificate: nil)
      l = listener(name)
      l.listener_port listener_port
      l.listener_protocol listener_protocol
      l.instance_port instance_port
      l.instance_protocol instance_protocol
      l.certificate certificate unless certificate.nil?
    end

    def build_health_target
      "#{health_protocol.to_s.upcase}:#{health_port}#{health_path if [:http, :https].include?(health_protocol)}"
    end

    def properties
      # TODO: Implement AccessLoggingPolicy AppCookieStickinessPolicy, LBCoolieStickinessPolicy, Policies
      # Not Implementing: AvailabilityZones, Name

      props = {
          ConnectionSettings: { IdleTimeout: idle_timeout },
          CrossZone: cross_zone,
          HealthCheck: {
              HealthyThreshold: health_up_threshold,
              UnhealthyThreshold: health_down_threshold,
              Interval: health_interval,
              Timeout: health_timeout,
              Target: build_health_target
          },
          Listeners: listeners,
          Scheme: internal? ? :internal : :'internet-facing',
          Subnets: ref(service.vpc.subnets)
      }

      props[:ConnectionDrainingPolicy] = { Enabled: true, Timeout: connection_drain_seconds } if connection_drain_seconds
      props[:Instances] = ref(instances) if set_instances?
      props[:SecurityGroups] = ref(security_groups) unless security_groups.empty?

      props
    end
  end
end