{-# LANGUAGE DataKinds                   #-}
{-# LANGUAGE DeriveGeneric               #-}
{-# LANGUAGE FlexibleInstances           #-}
{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
{-# LANGUAGE LambdaCase                  #-}
{-# LANGUAGE NoImplicitPrelude           #-}
{-# LANGUAGE OverloadedStrings           #-}
{-# LANGUAGE RecordWildCards             #-}
{-# LANGUAGE TypeFamilies                #-}

{-# OPTIONS_GHC -fno-warn-unused-imports #-}

-- Module      : Network.AWS.Redshift.CreateCluster
-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
-- License     : This Source Code Form is subject to the terms of
--               the Mozilla Public License, v. 2.0.
--               A copy of the MPL can be found in the LICENSE file or
--               you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)

-- | Creates a new cluster. To create the cluster in virtual private cloud
-- (VPC), you must provide cluster subnet group name. If you don't provide a
-- cluster subnet group name or the cluster security group parameter, Amazon
-- Redshift creates a non-VPC cluster, it associates the default cluster
-- security group with the cluster. For more information about managing
-- clusters, go to Amazon Redshift Clusters in the Amazon Redshift Cluster
-- Management Guide .
--
-- <http://docs.aws.amazon.com/redshift/latest/APIReference/API_CreateCluster.html>
module Network.AWS.Redshift.CreateCluster
    (
    -- * Request
      CreateCluster
    -- ** Request constructor
    , createCluster
    -- ** Request lenses
    , ccAllowVersionUpgrade
    , ccAutomatedSnapshotRetentionPeriod
    , ccAvailabilityZone
    , ccClusterIdentifier
    , ccClusterParameterGroupName
    , ccClusterSecurityGroups
    , ccClusterSubnetGroupName
    , ccClusterType
    , ccClusterVersion
    , ccDBName
    , ccElasticIp
    , ccEncrypted
    , ccHsmClientCertificateIdentifier
    , ccHsmConfigurationIdentifier
    , ccKmsKeyId
    , ccMasterUserPassword
    , ccMasterUsername
    , ccNodeType
    , ccNumberOfNodes
    , ccPort
    , ccPreferredMaintenanceWindow
    , ccPubliclyAccessible
    , ccTags
    , ccVpcSecurityGroupIds

    -- * Response
    , CreateClusterResponse
    -- ** Response constructor
    , createClusterResponse
    -- ** Response lenses
    , ccrCluster
    ) where

import Network.AWS.Prelude
import Network.AWS.Request.Query
import Network.AWS.Redshift.Types
import qualified GHC.Exts

data CreateCluster = CreateCluster
    { _ccAllowVersionUpgrade              :: Maybe Bool
    , _ccAutomatedSnapshotRetentionPeriod :: Maybe Int
    , _ccAvailabilityZone                 :: Maybe Text
    , _ccClusterIdentifier                :: Text
    , _ccClusterParameterGroupName        :: Maybe Text
    , _ccClusterSecurityGroups            :: List "ClusterSecurityGroupName" Text
    , _ccClusterSubnetGroupName           :: Maybe Text
    , _ccClusterType                      :: Maybe Text
    , _ccClusterVersion                   :: Maybe Text
    , _ccDBName                           :: Maybe Text
    , _ccElasticIp                        :: Maybe Text
    , _ccEncrypted                        :: Maybe Bool
    , _ccHsmClientCertificateIdentifier   :: Maybe Text
    , _ccHsmConfigurationIdentifier       :: Maybe Text
    , _ccKmsKeyId                         :: Maybe Text
    , _ccMasterUserPassword               :: Text
    , _ccMasterUsername                   :: Text
    , _ccNodeType                         :: Text
    , _ccNumberOfNodes                    :: Maybe Int
    , _ccPort                             :: Maybe Int
    , _ccPreferredMaintenanceWindow       :: Maybe Text
    , _ccPubliclyAccessible               :: Maybe Bool
    , _ccTags                             :: List "Tag" Tag
    , _ccVpcSecurityGroupIds              :: List "VpcSecurityGroupId" Text
    } deriving (Eq, Show)

-- | 'CreateCluster' constructor.
--
-- The fields accessible through corresponding lenses are:
--
-- * 'ccAllowVersionUpgrade' @::@ 'Maybe' 'Bool'
--
-- * 'ccAutomatedSnapshotRetentionPeriod' @::@ 'Maybe' 'Int'
--
-- * 'ccAvailabilityZone' @::@ 'Maybe' 'Text'
--
-- * 'ccClusterIdentifier' @::@ 'Text'
--
-- * 'ccClusterParameterGroupName' @::@ 'Maybe' 'Text'
--
-- * 'ccClusterSecurityGroups' @::@ ['Text']
--
-- * 'ccClusterSubnetGroupName' @::@ 'Maybe' 'Text'
--
-- * 'ccClusterType' @::@ 'Maybe' 'Text'
--
-- * 'ccClusterVersion' @::@ 'Maybe' 'Text'
--
-- * 'ccDBName' @::@ 'Maybe' 'Text'
--
-- * 'ccElasticIp' @::@ 'Maybe' 'Text'
--
-- * 'ccEncrypted' @::@ 'Maybe' 'Bool'
--
-- * 'ccHsmClientCertificateIdentifier' @::@ 'Maybe' 'Text'
--
-- * 'ccHsmConfigurationIdentifier' @::@ 'Maybe' 'Text'
--
-- * 'ccKmsKeyId' @::@ 'Maybe' 'Text'
--
-- * 'ccMasterUserPassword' @::@ 'Text'
--
-- * 'ccMasterUsername' @::@ 'Text'
--
-- * 'ccNodeType' @::@ 'Text'
--
-- * 'ccNumberOfNodes' @::@ 'Maybe' 'Int'
--
-- * 'ccPort' @::@ 'Maybe' 'Int'
--
-- * 'ccPreferredMaintenanceWindow' @::@ 'Maybe' 'Text'
--
-- * 'ccPubliclyAccessible' @::@ 'Maybe' 'Bool'
--
-- * 'ccTags' @::@ ['Tag']
--
-- * 'ccVpcSecurityGroupIds' @::@ ['Text']
--
createCluster :: Text -- ^ 'ccClusterIdentifier'
              -> Text -- ^ 'ccNodeType'
              -> Text -- ^ 'ccMasterUsername'
              -> Text -- ^ 'ccMasterUserPassword'
              -> CreateCluster
createCluster p1 p2 p3 p4 = CreateCluster
    { _ccClusterIdentifier                = p1
    , _ccNodeType                         = p2
    , _ccMasterUsername                   = p3
    , _ccMasterUserPassword               = p4
    , _ccDBName                           = Nothing
    , _ccClusterType                      = Nothing
    , _ccClusterSecurityGroups            = mempty
    , _ccVpcSecurityGroupIds              = mempty
    , _ccClusterSubnetGroupName           = Nothing
    , _ccAvailabilityZone                 = Nothing
    , _ccPreferredMaintenanceWindow       = Nothing
    , _ccClusterParameterGroupName        = Nothing
    , _ccAutomatedSnapshotRetentionPeriod = Nothing
    , _ccPort                             = Nothing
    , _ccClusterVersion                   = Nothing
    , _ccAllowVersionUpgrade              = Nothing
    , _ccNumberOfNodes                    = Nothing
    , _ccPubliclyAccessible               = Nothing
    , _ccEncrypted                        = Nothing
    , _ccHsmClientCertificateIdentifier   = Nothing
    , _ccHsmConfigurationIdentifier       = Nothing
    , _ccElasticIp                        = Nothing
    , _ccTags                             = mempty
    , _ccKmsKeyId                         = Nothing
    }

-- | If true, major version upgrades can be applied during the maintenance
-- window to the Amazon Redshift engine that is running on the cluster. When
-- a new major version of the Amazon Redshift engine is released, you can
-- request that the service automatically apply upgrades during the
-- maintenance window to the Amazon Redshift engine that is running on your
-- cluster. Default: true.
ccAllowVersionUpgrade :: Lens' CreateCluster (Maybe Bool)
ccAllowVersionUpgrade =
    lens _ccAllowVersionUpgrade (\s a -> s { _ccAllowVersionUpgrade = a })

-- | The number of days that automated snapshots are retained. If the value is
-- 0, automated snapshots are disabled. Even if automated snapshots are
-- disabled, you can still create manual snapshots when you want with
-- CreateClusterSnapshot. Default: 1 Constraints: Must be a value from 0 to
-- 35.
ccAutomatedSnapshotRetentionPeriod :: Lens' CreateCluster (Maybe Int)
ccAutomatedSnapshotRetentionPeriod =
    lens _ccAutomatedSnapshotRetentionPeriod
        (\s a -> s { _ccAutomatedSnapshotRetentionPeriod = a })

-- | The EC2 Availability Zone (AZ) in which you want Amazon Redshift to
-- provision the cluster. For example, if you have several EC2 instances
-- running in a specific Availability Zone, then you might want the cluster
-- to be provisioned in the same zone in order to decrease network latency.
-- Default: A random, system-chosen Availability Zone in the region that is
-- specified by the endpoint. Example: us-east-1d Constraint: The specified
-- Availability Zone must be in the same region as the current endpoint.
ccAvailabilityZone :: Lens' CreateCluster (Maybe Text)
ccAvailabilityZone =
    lens _ccAvailabilityZone (\s a -> s { _ccAvailabilityZone = a })

-- | A unique identifier for the cluster. You use this identifier to refer to
-- the cluster for any subsequent cluster operations such as deleting or
-- modifying. The identifier also appears in the Amazon Redshift console.
-- Constraints: Must contain from 1 to 63 alphanumeric characters or
-- hyphens. Alphabetic characters must be lowercase. First character must be
-- a letter. Cannot end with a hyphen or contain two consecutive hyphens.
-- Must be unique for all clusters within an AWS account. Example:
-- myexamplecluster.
ccClusterIdentifier :: Lens' CreateCluster Text
ccClusterIdentifier =
    lens _ccClusterIdentifier (\s a -> s { _ccClusterIdentifier = a })

-- | The name of the parameter group to be associated with this cluster.
-- Default: The default Amazon Redshift cluster parameter group. For
-- information about the default parameter group, go to Working with Amazon
-- Redshift Parameter Groups Constraints: Must be 1 to 255 alphanumeric
-- characters or hyphens. First character must be a letter. Cannot end with
-- a hyphen or contain two consecutive hyphens.
ccClusterParameterGroupName :: Lens' CreateCluster (Maybe Text)
ccClusterParameterGroupName =
    lens _ccClusterParameterGroupName
        (\s a -> s { _ccClusterParameterGroupName = a })

-- | A list of security groups to be associated with this cluster. Default:
-- The default cluster security group for Amazon Redshift.
ccClusterSecurityGroups :: Lens' CreateCluster [Text]
ccClusterSecurityGroups =
    lens _ccClusterSecurityGroups (\s a -> s { _ccClusterSecurityGroups = a })
        . _List

-- | The name of a cluster subnet group to be associated with this cluster. If
-- this parameter is not provided the resulting cluster will be deployed
-- outside virtual private cloud (VPC).
ccClusterSubnetGroupName :: Lens' CreateCluster (Maybe Text)
ccClusterSubnetGroupName =
    lens _ccClusterSubnetGroupName
        (\s a -> s { _ccClusterSubnetGroupName = a })

-- | The type of the cluster. When cluster type is specified as single-node,
-- the NumberOfNodes parameter is not required. multi-node, the
-- NumberOfNodes parameter is required. Valid Values: multi-node |
-- single-node Default: multi-node.
ccClusterType :: Lens' CreateCluster (Maybe Text)
ccClusterType = lens _ccClusterType (\s a -> s { _ccClusterType = a })

-- | The version of the Amazon Redshift engine software that you want to
-- deploy on the cluster. The version selected runs on all the nodes in the
-- cluster. Constraints: Only version 1.0 is currently available. Example:
-- 1.0.
ccClusterVersion :: Lens' CreateCluster (Maybe Text)
ccClusterVersion = lens _ccClusterVersion (\s a -> s { _ccClusterVersion = a })

-- | The name of the first database to be created when the cluster is created.
-- To create additional databases after the cluster is created, connect to
-- the cluster with a SQL client and use SQL commands to create a database.
-- For more information, go to Create a Database in the Amazon Redshift
-- Database Developer Guide. Default: dev Constraints: Must contain 1 to 64
-- alphanumeric characters. Must contain only lowercase letters. Cannot be a
-- word that is reserved by the service. A list of reserved words can be
-- found in Reserved Words in the Amazon Redshift Database Developer Guide.
ccDBName :: Lens' CreateCluster (Maybe Text)
ccDBName = lens _ccDBName (\s a -> s { _ccDBName = a })

-- | The Elastic IP (EIP) address for the cluster. Constraints: The cluster
-- must be provisioned in EC2-VPC and publicly-accessible through an
-- Internet gateway. For more information about provisioning clusters in
-- EC2-VPC, go to Supported Platforms to Launch Your Cluster in the Amazon
-- Redshift Cluster Management Guide.
ccElasticIp :: Lens' CreateCluster (Maybe Text)
ccElasticIp = lens _ccElasticIp (\s a -> s { _ccElasticIp = a })

-- | If true, the data in the cluster is encrypted at rest. Default: false.
ccEncrypted :: Lens' CreateCluster (Maybe Bool)
ccEncrypted = lens _ccEncrypted (\s a -> s { _ccEncrypted = a })

-- | Specifies the name of the HSM client certificate the Amazon Redshift
-- cluster uses to retrieve the data encryption keys stored in an HSM.
ccHsmClientCertificateIdentifier :: Lens' CreateCluster (Maybe Text)
ccHsmClientCertificateIdentifier =
    lens _ccHsmClientCertificateIdentifier
        (\s a -> s { _ccHsmClientCertificateIdentifier = a })

-- | Specifies the name of the HSM configuration that contains the information
-- the Amazon Redshift cluster can use to retrieve and store keys in an HSM.
ccHsmConfigurationIdentifier :: Lens' CreateCluster (Maybe Text)
ccHsmConfigurationIdentifier =
    lens _ccHsmConfigurationIdentifier
        (\s a -> s { _ccHsmConfigurationIdentifier = a })

-- | The AWS Key Management Service (KMS) key ID of the encryption key that
-- you want to use to encrypt data in the cluster.
ccKmsKeyId :: Lens' CreateCluster (Maybe Text)
ccKmsKeyId = lens _ccKmsKeyId (\s a -> s { _ccKmsKeyId = a })

-- | The password associated with the master user account for the cluster that
-- is being created. Constraints: Must be between 8 and 64 characters in
-- length. Must contain at least one uppercase letter. Must contain at least
-- one lowercase letter. Must contain one number. Can be any printable ASCII
-- character (ASCII code 33 to 126) except ' (single quote), " (double
-- quote), \, /, @, or space.
ccMasterUserPassword :: Lens' CreateCluster Text
ccMasterUserPassword =
    lens _ccMasterUserPassword (\s a -> s { _ccMasterUserPassword = a })

-- | The user name associated with the master user account for the cluster
-- that is being created. Constraints: Must be 1 - 128 alphanumeric
-- characters. First character must be a letter. Cannot be a reserved word.
-- A list of reserved words can be found in Reserved Words in the Amazon
-- Redshift Database Developer Guide.
ccMasterUsername :: Lens' CreateCluster Text
ccMasterUsername = lens _ccMasterUsername (\s a -> s { _ccMasterUsername = a })

-- | The node type to be provisioned for the cluster. For information about
-- node types, go to Working with Clusters in the Amazon Redshift Cluster
-- Management Guide. Valid Values: dw1.xlarge | dw1.8xlarge | dw2.large |
-- dw2.8xlarge.
ccNodeType :: Lens' CreateCluster Text
ccNodeType = lens _ccNodeType (\s a -> s { _ccNodeType = a })

-- | The number of compute nodes in the cluster. This parameter is required
-- when the ClusterType parameter is specified as multi-node. For
-- information about determining how many nodes you need, go to Working with
-- Clusters in the Amazon Redshift Cluster Management Guide. If you don't
-- specify this parameter, you get a single-node cluster. When requesting a
-- multi-node cluster, you must specify the number of nodes that you want in
-- the cluster. Default: 1 Constraints: Value must be at least 1 and no more
-- than 100.
ccNumberOfNodes :: Lens' CreateCluster (Maybe Int)
ccNumberOfNodes = lens _ccNumberOfNodes (\s a -> s { _ccNumberOfNodes = a })

-- | The port number on which the cluster accepts incoming connections. The
-- cluster is accessible only via the JDBC and ODBC connection strings. Part
-- of the connection string requires the port on which the cluster will
-- listen for incoming connections. Default: 5439 Valid Values: 1150-65535.
ccPort :: Lens' CreateCluster (Maybe Int)
ccPort = lens _ccPort (\s a -> s { _ccPort = a })

-- | The weekly time range (in UTC) during which automated cluster maintenance
-- can occur. Format: ddd:hh24:mi-ddd:hh24:mi Default: A 30-minute window
-- selected at random from an 8-hour block of time per region, occurring on
-- a random day of the week. For more information about the time blocks for
-- each region, see Maintenance Windows in Amazon Redshift Cluster
-- Management Guide. Valid Days: Mon | Tue | Wed | Thu | Fri | Sat | Sun
-- Constraints: Minimum 30-minute window.
ccPreferredMaintenanceWindow :: Lens' CreateCluster (Maybe Text)
ccPreferredMaintenanceWindow =
    lens _ccPreferredMaintenanceWindow
        (\s a -> s { _ccPreferredMaintenanceWindow = a })

-- | If true, the cluster can be accessed from a public network.
ccPubliclyAccessible :: Lens' CreateCluster (Maybe Bool)
ccPubliclyAccessible =
    lens _ccPubliclyAccessible (\s a -> s { _ccPubliclyAccessible = a })

-- | A list of tag instances.
ccTags :: Lens' CreateCluster [Tag]
ccTags = lens _ccTags (\s a -> s { _ccTags = a }) . _List

-- | A list of Virtual Private Cloud (VPC) security groups to be associated
-- with the cluster. Default: The default VPC security group is associated
-- with the cluster.
ccVpcSecurityGroupIds :: Lens' CreateCluster [Text]
ccVpcSecurityGroupIds =
    lens _ccVpcSecurityGroupIds (\s a -> s { _ccVpcSecurityGroupIds = a })
        . _List

newtype CreateClusterResponse = CreateClusterResponse
    { _ccrCluster :: Maybe Cluster
    } deriving (Eq, Show)

-- | 'CreateClusterResponse' constructor.
--
-- The fields accessible through corresponding lenses are:
--
-- * 'ccrCluster' @::@ 'Maybe' 'Cluster'
--
createClusterResponse :: CreateClusterResponse
createClusterResponse = CreateClusterResponse
    { _ccrCluster = Nothing
    }

ccrCluster :: Lens' CreateClusterResponse (Maybe Cluster)
ccrCluster = lens _ccrCluster (\s a -> s { _ccrCluster = a })

instance ToPath CreateCluster where
    toPath = const "/"

instance ToQuery CreateCluster where
    toQuery CreateCluster{..} = mconcat
        [ "AllowVersionUpgrade"              =? _ccAllowVersionUpgrade
        , "AutomatedSnapshotRetentionPeriod" =? _ccAutomatedSnapshotRetentionPeriod
        , "AvailabilityZone"                 =? _ccAvailabilityZone
        , "ClusterIdentifier"                =? _ccClusterIdentifier
        , "ClusterParameterGroupName"        =? _ccClusterParameterGroupName
        , "ClusterSecurityGroups"            =? _ccClusterSecurityGroups
        , "ClusterSubnetGroupName"           =? _ccClusterSubnetGroupName
        , "ClusterType"                      =? _ccClusterType
        , "ClusterVersion"                   =? _ccClusterVersion
        , "DBName"                           =? _ccDBName
        , "ElasticIp"                        =? _ccElasticIp
        , "Encrypted"                        =? _ccEncrypted
        , "HsmClientCertificateIdentifier"   =? _ccHsmClientCertificateIdentifier
        , "HsmConfigurationIdentifier"       =? _ccHsmConfigurationIdentifier
        , "KmsKeyId"                         =? _ccKmsKeyId
        , "MasterUserPassword"               =? _ccMasterUserPassword
        , "MasterUsername"                   =? _ccMasterUsername
        , "NodeType"                         =? _ccNodeType
        , "NumberOfNodes"                    =? _ccNumberOfNodes
        , "Port"                             =? _ccPort
        , "PreferredMaintenanceWindow"       =? _ccPreferredMaintenanceWindow
        , "PubliclyAccessible"               =? _ccPubliclyAccessible
        , "Tags"                             =? _ccTags
        , "VpcSecurityGroupIds"              =? _ccVpcSecurityGroupIds
        ]

instance ToHeaders CreateCluster

instance AWSRequest CreateCluster where
    type Sv CreateCluster = Redshift
    type Rs CreateCluster = CreateClusterResponse

    request  = post "CreateCluster"
    response = xmlResponse

instance FromXML CreateClusterResponse where
    parseXML = withElement "CreateClusterResult" $ \x -> CreateClusterResponse
        <$> x .@? "Cluster"