requestSpotInstances
    :: (MonadResource m, MonadBaseControl IO m)
    => RequestSpotInstancesParam
    -> EC2 m [SpotInstanceRequest]
requestSpotInstances param =
    ec2Query "RequestSpotInstances" params $
        itemsSet "spotInstanceRequestSet" spotInstanceRequestConv
  where
    params =
        [ "SpotPrice" |= requestSpotInstancesSpotPrice param
        , "InstanceCount" |=? requestSpotInstancesCount param
        , "Type" |=? requestSpotInstancesType param
        , "ValidFrom" |=? requestSpotInstancesValidFrom param
        , "ValidUntil" |=? requestSpotInstancesValidUntil param
        , "LaunchGroup" |=? requestSpotInstancesLaunchGroup param
        , "AvailabilityZoneGroup" |=? requestSpotInstancesLaunchGroup param
        , "LaunchSpecification" |.
          [ "ImageId" |= requestSpotInstancesImageId param
          , "KeyName" |=? requestSpotInstancesKeyName param
          , "SecurityGroupId" |.#= requestSpotInstancesSecurityGroupIds param
          , "SecurityGroup" |.#= requestSpotInstancesSecurityGroups param
          , "UserData" |=? requestSpotInstancesUserData param
          , "InstanceType" |= requestSpotInstancesInstanceType param
          , "Placement" |.
              [ "AvailabilityZone" |=?
                  requestSpotInstancesAvailabilityZone param
              , "GroupName" |=?
                  requestSpotInstancesPlacementGroup param
              ]
          , "KernelId" |=? requestSpotInstancesKernelId param
          , "RamdiskId" |=? requestSpotInstancesRamdiskId param
          , blockDeviceMappingsParam $
              requestSpotInstancesBlockDeviceMappings param
          , "Monitoring" |.+ "Enabled" |=?
              requestSpotInstancesMonitoringEnabled param
          , "SubnetId" |=? requestSpotInstancesSubnetId param
          , "NetworkInterface" |.#. map networkInterfaceParams
              (requestSpotInstancesNetworkInterfaces param)
          , "IamInstanceProfile" |.? iamInstanceProfileParams <$>
              requestSpotInstancesIamInstancesProfile param
          , "EbsOptimized" |=?
              requestSpotInstancesEbsOptimized param
          ]
        ]
    iamInstanceProfileParams iam =
        [ "Arn" |= iamInstanceProfileArn iam
        , "Name" |= iamInstanceProfileId iam
        ]

-- | RequestSpotInstances parameter utility
requestSpotInstances
    :: (MonadResource m, MonadBaseControl IO m)
    => RequestSpotInstancesParam
    -> EC2 m [SpotInstanceRequest]
requestSpotInstances param =
    ec2Query "RequestSpotInstances" params $
        itemsSet "spotInstanceRequestSet" spotInstanceRequestConv
  where
    params =
        [ "SpotPrice" |= requestSpotInstancesSpotPrice param
        , "InstanceCount" |=? requestSpotInstancesCount param
        , "Type" |=? requestSpotInstancesType param
        , "ValidFrom" |=? requestSpotInstancesValidFrom param
        , "ValidUntil" |=? requestSpotInstancesValidUntil param
        , "LaunchGroup" |=? requestSpotInstancesLaunchGroup param
        , "AvailabilityZoneGroup" |=? requestSpotInstancesLaunchGroup param
        , "LaunchSpecification" |.
          [ "ImageId" |= requestSpotInstancesImageId param
          , "KeyName" |=? requestSpotInstancesKeyName param
          , "SecurityGroupId" |.#= requestSpotInstancesSecurityGroupIds param
          , "SecurityGroup" |.#= requestSpotInstancesSecurityGroups param
          , "UserData" |=? requestSpotInstancesUserData param
          , "InstanceType" |= requestSpotInstancesInstanceType param
          , "Placement" |.
              [ "AvailabilityZone" |=?
                  requestSpotInstancesAvailabilityZone param
              , "GroupName" |=?
                  requestSpotInstancesPlacementGroup param
              ]
          , "KernelId" |=? requestSpotInstancesKernelId param
          , "RamdiskId" |=? requestSpotInstancesRamdiskId param
          , blockDeviceMappingsParam $
              requestSpotInstancesBlockDeviceMappings param
          , "Monitoring" |.+ "Enabled" |=?
              requestSpotInstancesMonitoringEnabled param
          , "SubnetId" |=? requestSpotInstancesSubnetId param
          , "NetworkInterface" |.#. map networkInterfaceParams
              (requestSpotInstancesNetworkInterfaces param)
          , "IamInstanceProfile" |.? iamInstanceProfileParams <$>
              requestSpotInstancesIamInstancesProfile param
          , "EbsOptimized" |=?
              requestSpotInstancesEbsOptimized param
          ]
        ]
    iamInstanceProfileParams iam =
        [ "Arn" |= iamInstanceProfileArn iam
        , "Name" |= iamInstanceProfileId iam
        ]

-- | RequestSpotInstances parameter utility
requestSpotInstances param =
    ec2Query "RequestSpotInstances" params $
        itemsSet "spotInstanceRequestSet" spotInstanceRequestConv
  where
    params =
        [ "SpotPrice" |= requestSpotInstancesSpotPrice param
        , "InstanceCount" |=? requestSpotInstancesCount param
        , "Type" |=? requestSpotInstancesType param
        , "ValidFrom" |=? requestSpotInstancesValidFrom param
        , "ValidUntil" |=? requestSpotInstancesValidUntil param
        , "LaunchGroup" |=? requestSpotInstancesLaunchGroup param
        , "AvailabilityZoneGroup" |=? requestSpotInstancesLaunchGroup param
        , "LaunchSpecification" |.
          [ "ImageId" |= requestSpotInstancesImageId param
          , "KeyName" |=? requestSpotInstancesKeyName param
          , "SecurityGroupId" |.#= requestSpotInstancesSecurityGroupIds param
          , "SecurityGroup" |.#= requestSpotInstancesSecurityGroups param
          , "UserData" |=? requestSpotInstancesUserData param
          , "InstanceType" |= requestSpotInstancesInstanceType param
          , "Placement" |.
              [ "AvailabilityZone" |=?
                  requestSpotInstancesAvailabilityZone param
              , "GroupName" |=?
                  requestSpotInstancesPlacementGroup param
              ]
          , "KernelId" |=? requestSpotInstancesKernelId param
          , "RamdiskId" |=? requestSpotInstancesRamdiskId param
          , blockDeviceMappingsParam $
              requestSpotInstancesBlockDeviceMappings param
          , "Monitoring" |.+ "Enabled" |=?
              requestSpotInstancesMonitoringEnabled param
          , "SubnetId" |=? requestSpotInstancesSubnetId param
          , "NetworkInterface" |.#. map networkInterfaceParams
              (requestSpotInstancesNetworkInterfaces param)
          , "IamInstanceProfile" |.? iamInstanceProfileParams <$>
              requestSpotInstancesIamInstancesProfile param
          , "EbsOptimized" |=?
              requestSpotInstancesEbsOptimized param
          ]
        ]
    iamInstanceProfileParams iam =
        [ "Arn" |= iamInstanceProfileArn iam
        , "Name" |= iamInstanceProfileId iam
        ]

-- | RequestSpotInstances parameter utility