class Inspec::Resources::WindowsFirewall

def access_property(property)

def access_property(property)
  @state[property]
end

def default_inbound_allowed?

def default_inbound_allowed?
  @state["default_inbound_action"] == "Allow"
end

def default_outbound_allowed?

def default_outbound_allowed?
  @state["default_outbound_action"] == "Allow"
end

def enabled?

def enabled?
  @state["enabled"]
end

def exist?

def exist?
  !@state.empty?
end

def initialize(profile = "Public")

def initialize(profile = "Public")
  @profile = profile
  @state = {}
  load_profile_cmd = load_firewall_profile(profile)
  cmd = inspec.powershell(load_profile_cmd)
  @state = JSON.load(cmd.stdout) unless cmd.stdout.empty?
end

def load_firewall_profile(profile_name)

def load_firewall_profile(profile_name)
  <<-EOH
    Get-TypeData -TypeName System.Array | Remove-TypeData # workaround for PS bug here: https://bit.ly/2SRMQ8M
    $profile = Get-NetFirewallProfile -Name "#{profile_name}"
    $count = @($profile | Get-NetFirewallRule).Count
    ([PSCustomObject]@{
      profile_name = $profile.Name
      profile = $profile.Profile.ToString()
      description = $profile.Description
      enabled = [bool]::Parse($profile.Enabled.ToString())
      default_inbound_action = $profile.DefaultInboundAction.ToString()
      default_outbound_action = $profile.DefaultOutboundAction.ToString()
      allow_inbound_rules = $profile.AllowInboundRules.ToString()
      allow_local_firewall_rules = $profile.AllowLocalFirewallRules.ToString()
      allow_local_ipsec_rules = $profile.AllowLocalIPsecRules.ToString()
      allow_user_apps = $profile.AllowUserApps.ToString()
      allow_user_ports = $profile.AllowUserPorts.ToString()
      allow_unicast_response_to_multicast = $profile.AllowUnicastResponseToMulticast.ToString()
      notify_on_listen = $profile.NotifyOnListen.ToString()
      enable_stealth_mode_for_ipsec = $profile.EnableStealthModeForIPsec.ToString()
      log_max_size_kilobytes = $profile.LogMaxSizeKilobytes
      log_allowed = $profile.LogAllowed.ToString()
      log_blocked = $profile.LogBlocked.ToString()
      log_ignored = $profile.LogIgnored.ToString()
      num_rules = $count
    }) | ConvertTo-Json
  EOH
end

def method_missing(method_name, *arguments, &_block)

Access to return values from Powershell via `its("PROPERTY")` and `have_PROPERTY "VALUE"`
def method_missing(method_name, *arguments, &_block)
  property = normalize_for_have_access(method_name)
  if method_name.to_s.start_with? "has_"
    expected_value = arguments.first
    respond_to_have(property, expected_value)
  else
    access_property(property)
  end
end

def normalize_for_have_access(property)

def normalize_for_have_access(property)
  property.to_s
    .delete_prefix("has_")
    .delete_suffix("?")
end

def resource_id

def resource_id
  @profile || "windows_firewall"
end

def respond_to_have(property, value)

def respond_to_have(property, value)
  @state[property] == value
end

def respond_to_missing?(method_name, _include_private = false)

def respond_to_missing?(method_name, _include_private = false)
  property = normalize_for_have_access(method_name)
  @state.key? property
end

def to_s

def to_s
  "Windows Firewall (Profile #{@profile})"
end