# frozen_string_literal: true

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

module Litany
  class ApplicationLoadBalancerListenerRule < Resource
    cfn_type 'AWS::ElasticLoadBalancingV2::ListenerRule'
    parent_resource :listener

    child_resource ApplicationLoadBalancerFixedResponse, :fixed_response, automatic: :on_access

    property :priority, nil, [1..99_999]

    # TODO: Looks like these should be properties, not collections
    property_collection :host, [], [String], required: false
    property_collection :path, [], [String], required: false

    resource_reference ApplicationLoadBalancerTargetGroup, :target_group, required: false

    # TODO: Docs suggest having one of each is actually valid
    validator :conditions do
      raise 'Listener rules require either a host and/or path condition to be set.' if !set_hosts? && !set_paths?

      if set_hosts?
        raise 'Host may only be set to a String or Array of Strings matching: `/^[A-Za-z0-9.\-?*]*$/`.' unless hosts.all? { |v| /^[A-Za-z0-9.\-?*]*$/.match(v) }
        raise 'Host values may only have three wildcard statements.' unless hosts.all? { |v| v.count('*?') <= 3 }
      end

      if set_paths?
        raise 'Path may only be set to a String or Array of Strings matching: `/^[A-Za-z0-9_\-.$\/~"\'@:+*?]*$/`.' unless paths.all? { |v| /^[A-Za-z0-9_\-.$\/~"'@:+*?]*$/.match(v) }
        raise 'Path values may only have three wildcard statements.' unless paths.all? { |v| v.count('*?') <= 3 }
      end
    end

    validator :action_jeopardy do
      raise 'You must specify either a fixed_response or a target_group but not both.' unless set_fixed_response? ^ set_target_group?
    end

    def properties
      # Not Implementing: multiple actions

      props = {
        Actions: [],
        Conditions: [],
        ListenerArn: ref(listener),
        Priority: priority
      }

      if set_paths?
        props[:Conditions] << {
          Field: :'path-pattern',
          Values: paths
        }
      end

      if set_hosts?
        props[:Conditions] << {
          Field: :'host-header',
          Values: hosts
        }
      end

      props[:Actions] << { FixedResponseConfig: fixed_response, Type: 'fixed-response' } if set_fixed_response?
      props[:Actions] << { TargetGroupArn: ref(target_group), Type: :forward } if set_target_group?

      props
    end
  end
end
