/*******************************************************************************
 *  Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License"). You may not use
 *  this file except in compliance with the License. A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 *  or in the "license" file accompanying this file.
 *  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the
 *  specific language governing permissions and limitations under the License.
 * *****************************************************************************
 *
 *  AWS Tools for Windows (TM) PowerShell (TM)
 *
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Text;
using Amazon.PowerShell.Common;
using Amazon.Runtime;
using Amazon.KeyManagementService;
using Amazon.KeyManagementService.Model;
namespace Amazon.PowerShell.Cmdlets.KMS
{
    /// 
    /// Replicates a multi-Region key into the specified Region. This operation creates a
    /// multi-Region replica key based on a multi-Region primary key in a different Region
    /// of the same Amazon Web Services partition. You can create multiple replicas of a primary
    /// key, but each must be in a different Region. To create a multi-Region primary key,
    /// use the CreateKey operation.
    /// 
    ///  
    /// 
    /// This operation supports multi-Region keys, an KMS feature that lets you create
    /// multiple interoperable KMS keys in different Amazon Web Services Regions. Because
    /// these KMS keys have the same key ID, key material, and other metadata, you can use
    /// them interchangeably to encrypt data in one Amazon Web Services Region and decrypt
    /// it in a different Amazon Web Services Region without re-encrypting the data or making
    /// a cross-Region call. For more information about multi-Region keys, see Multi-Region
    /// keys in KMS in the Key Management Service Developer Guide.
    /// 
    /// A replica key is a fully-functional KMS key that can be used independently
    /// of its primary and peer replica keys. A primary key and its replica keys share properties
    /// that make them interoperable. They have the same key
    /// ID and key material. They also have the same key
    /// spec, key
    /// usage, key
    /// material origin, and automatic
    /// key rotation status. KMS automatically synchronizes these shared properties among
    /// related multi-Region keys. All other properties of a replica key can differ, including
    /// its key
    /// policy, tags,
    /// aliases,
    /// and Key
    /// states of KMS keys. KMS pricing and quotas for KMS keys apply to each primary
    /// key and replica key.
    /// 
    /// When this operation completes, the new replica key has a transient key state of Creating.
    /// This key state changes to Enabled (or PendingImport) after
    /// a few seconds when the process of creating the new replica key is complete. While
    /// the key state is Creating, you can manage key, but you cannot yet use
    /// it in cryptographic operations. If you are creating and using the replica key programmatically,
    /// retry on KMSInvalidStateException or call DescribeKey to
    /// check its KeyState value before using it. For details about the Creating
    /// key state, see Key
    /// states of KMS keys in the Key Management Service Developer Guide.
    /// 
    /// You cannot create more than one replica of a primary key in any Region. If the Region
    /// already includes a replica of the key you're trying to replicate, ReplicateKey
    /// returns an AlreadyExistsException error. If the key state of the existing
    /// replica is PendingDeletion, you can cancel the scheduled key deletion
    /// (CancelKeyDeletion) or wait for the key to be deleted. The new replica key
    /// you create will have the same shared
    /// properties as the original replica key.
    /// 
    /// The CloudTrail log of a ReplicateKey operation records a ReplicateKey
    /// operation in the primary key's Region and a CreateKey operation in the replica
    /// key's Region.
    /// 
    /// If you replicate a multi-Region primary key with imported key material, the replica
    /// key is created with no key material. You must import the same key material that you
    /// imported into the primary key. For details, see Importing
    /// key material into multi-Region keys in the Key Management Service Developer
    /// Guide.
    /// 
    /// To convert a replica key to a primary key, use the UpdatePrimaryRegion operation.
    /// ReplicateKey uses different default values for the KeyPolicy
    /// and Tags parameters than those used in the KMS console. For details,
    /// see the parameter descriptions.
    /// Cross-account use: No. You cannot use this operation to create a replica key
    /// in a different Amazon Web Services account. 
    /// Required permissions: 
    /// kms:ReplicateKey on the primary key (in the primary key's Region). Include
    /// this permission in the primary key's key policy.
    /// kms:CreateKey in an IAM policy in the replica Region.
    /// - 
    /// To use the 
Tags parameter, kms:TagResource in an IAM policy
    /// in the replica Region.
    ///  
Related operations
    /// 
    [Cmdlet("New", "KMSReplicaKey", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)]
    [OutputType("Amazon.KeyManagementService.Model.ReplicateKeyResponse")]
    [AWSCmdlet("Calls the AWS Key Management Service ReplicateKey API operation.", Operation = new[] {"ReplicateKey"}, SelectReturnType = typeof(Amazon.KeyManagementService.Model.ReplicateKeyResponse))]
    [AWSCmdletOutput("Amazon.KeyManagementService.Model.ReplicateKeyResponse",
        "This cmdlet returns an Amazon.KeyManagementService.Model.ReplicateKeyResponse object containing multiple properties. The object can also be referenced from properties attached to the cmdlet entry in the $AWSHistory stack."
    )]
    public partial class NewKMSReplicaKeyCmdlet : AmazonKeyManagementServiceClientCmdlet, IExecutor
    {
        
        #region Parameter BypassPolicyLockoutSafetyCheck
        /// 
        /// 
        /// Skips ("bypasses") the key policy lockout safety check. The default value is false.Setting this value to true increases the risk that the KMS key becomes unmanageable.
        /// Do not set this value to true indiscriminately.For more information, see Default
        /// key policy in the Key Management Service Developer Guide.Use this parameter only when you intend to prevent the principal that is making the
        /// request from making a subsequent PutKeyPolicy request on the KMS key.
        /// 
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public System.Boolean? BypassPolicyLockoutSafetyCheck { get; set; }
        #endregion
        
        #region Parameter Description
        /// 
        /// 
        /// A description of the KMS key. The default value is an empty string (no description).Do not include confidential or sensitive information in this field. This field may
        /// be displayed in plaintext in CloudTrail logs and other output.The description is not a shared property of multi-Region keys. You can specify the
        /// same description or a different description for each key in a set of related multi-Region
        /// keys. KMS does not synchronize this property.
        /// 
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public System.String Description { get; set; }
        #endregion
        
        #region Parameter KeyId
        /// 
        /// 
        /// Identifies the multi-Region primary key that is being replicated. To determine whether
        /// a KMS key is a multi-Region primary key, use the DescribeKey operation to check
        /// the value of the MultiRegionKeyType property.Specify the key ID or key ARN of a multi-Region primary key.For example:- Key ID: 
mrk-1234abcd12ab34cd56ef1234567890ab - Key ARN: 
arn:aws:kms:us-east-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab 
To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
        /// 
        /// 
        #if !MODULAR
        [System.Management.Automation.Parameter(Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true)]
        #else
        [System.Management.Automation.Parameter(Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, Mandatory = true)]
        [System.Management.Automation.AllowEmptyString]
        [System.Management.Automation.AllowNull]
        #endif
        [Amazon.PowerShell.Common.AWSRequiredParameter]
        public System.String KeyId { get; set; }
        #endregion
        
        #region Parameter Policy
        /// 
        /// 
        /// The key policy to attach to the KMS key. This parameter is optional. If you do not
        /// provide a key policy, KMS attaches the default
        /// key policy to the KMS key.The key policy is not a shared property of multi-Region keys. You can specify the
        /// same key policy or a different key policy for each key in a set of related multi-Region
        /// keys. KMS does not synchronize this property.If you provide a key policy, it must meet the following criteria:- The key policy must allow the calling principal to make a subsequent 
PutKeyPolicy
        /// request on the KMS key. This reduces the risk that the KMS key becomes unmanageable.
        /// For more information, see Default
        /// key policy in the Key Management Service Developer Guide. (To omit this
        /// condition, set BypassPolicyLockoutSafetyCheck to true.) - Each statement in the key policy must contain one or more principals. The principals
        /// in the key policy must exist and be visible to KMS. When you create a new Amazon Web
        /// Services principal, you might need to enforce a delay before including the new principal
        /// in a key policy because the new principal might not be immediately visible to KMS.
        /// For more information, see Changes
        /// that I make are not always immediately visible in the Amazon Web Services Identity
        /// and Access Management User Guide.
 
A key policy document can include only the following characters:- Printable ASCII characters from the space character (
\u0020) through
        /// the end of the ASCII character range. - Printable characters in the Basic Latin and Latin-1 Supplement character set (through
        /// 
\u00FF). - The tab (
\u0009), line feed (\u000A), and carriage return
        /// (\u000D) special characters 
For information about key policies, see Key
        /// policies in KMS in the Key Management Service Developer Guide. For help
        /// writing and formatting a JSON policy document, see the IAM
        /// JSON Policy Reference in the Identity and Access Management User Guide.
        /// 
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public System.String Policy { get; set; }
        #endregion
        
        #region Parameter ReplicaRegion
        /// 
        /// 
        /// The Region ID of the Amazon Web Services Region for this replica key. Enter the Region ID, such as us-east-1 or ap-southeast-2.
        /// For a list of Amazon Web Services Regions in which KMS is supported, see KMS
        /// service endpoints in the Amazon Web Services General Reference.HMAC KMS keys are not supported in all Amazon Web Services Regions. If you try to
        /// replicate an HMAC KMS key in an Amazon Web Services Region in which HMAC keys are
        /// not supported, the ReplicateKey operation returns an UnsupportedOperationException.
        /// For a list of Regions in which HMAC KMS keys are supported, see HMAC
        /// keys in KMS in the Key Management Service Developer Guide.The replica must be in a different Amazon Web Services Region than its primary key
        /// and other replicas of that primary key, but in the same Amazon Web Services partition.
        /// KMS must be available in the replica Region. If the Region is not enabled by default,
        /// the Amazon Web Services account must be enabled in the Region. For information about
        /// Amazon Web Services partitions, see Amazon
        /// Resource Names (ARNs) in the Amazon Web Services General Reference. For
        /// information about enabling and disabling Regions, see Enabling
        /// a Region and Disabling
        /// a Region in the Amazon Web Services General Reference.
        /// 
        /// 
        #if !MODULAR
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        #else
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true, Mandatory = true)]
        [System.Management.Automation.AllowEmptyString]
        [System.Management.Automation.AllowNull]
        #endif
        [Amazon.PowerShell.Common.AWSRequiredParameter]
        public System.String ReplicaRegion { get; set; }
        #endregion
        
        #region Parameter Tag
        /// 
        /// 
        /// Assigns one or more tags to the replica key. Use this parameter to tag the KMS key
        /// when it is created. To tag an existing KMS key, use the TagResource operation.Do not include confidential or sensitive information in this field. This field may
        /// be displayed in plaintext in CloudTrail logs and other output.Tagging or untagging a KMS key can allow or deny permission to the KMS key. For details,
        /// see ABAC
        /// for KMS in the Key Management Service Developer Guide.To use this parameter, you must have kms:TagResource
        /// permission in an IAM policy.Tags are not a shared property of multi-Region keys. You can specify the same tags
        /// or different tags for each key in a set of related multi-Region keys. KMS does not
        /// synchronize this property.Each tag consists of a tag key and a tag value. Both the tag key and the tag value
        /// are required, but the tag value can be an empty (null) string. You cannot have more
        /// than one tag on a KMS key with the same tag key. If you specify an existing tag key
        /// with a different tag value, KMS replaces the current tag value with the specified
        /// one.When you add tags to an Amazon Web Services resource, Amazon Web Services generates
        /// a cost allocation report with usage and costs aggregated by tags. Tags can also be
        /// used to control access to a KMS key. For details, see Tagging
        /// Keys.
        /// 
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        [Alias("Tags")]
        public Amazon.KeyManagementService.Model.Tag[] Tag { get; set; }
        #endregion
        
        #region Parameter Select
        /// 
        /// Use the -Select parameter to control the cmdlet output. The default value is '*'.
        /// Specifying -Select '*' will result in the cmdlet returning the whole service response (Amazon.KeyManagementService.Model.ReplicateKeyResponse).
        /// Specifying the name of a property of type Amazon.KeyManagementService.Model.ReplicateKeyResponse will result in that property being returned.
        /// Specifying -Select '^ParameterName' will result in the cmdlet returning the selected cmdlet parameter value.
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public string Select { get; set; } = "*";
        #endregion
        
        #region Parameter PassThru
        /// 
        /// Changes the cmdlet behavior to return the value passed to the KeyId parameter.
        /// The -PassThru parameter is deprecated, use -Select '^KeyId' instead. This parameter will be removed in a future version.
        /// 
        [System.Obsolete("The -PassThru parameter is deprecated, use -Select '^KeyId' instead. This parameter will be removed in a future version.")]
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public SwitchParameter PassThru { get; set; }
        #endregion
        
        #region Parameter Force
        /// 
        /// This parameter overrides confirmation prompts to force 
        /// the cmdlet to continue its operation. This parameter should always
        /// be used with caution.
        /// 
        [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
        public SwitchParameter Force { get; set; }
        #endregion
        
        protected override void ProcessRecord()
        {
            this._AWSSignerType = "v4";
            base.ProcessRecord();
            
            var resourceIdentifiersText = FormatParameterValuesForConfirmationMsg(nameof(this.KeyId), MyInvocation.BoundParameters);
            if (!ConfirmShouldProceed(this.Force.IsPresent, resourceIdentifiersText, "New-KMSReplicaKey (ReplicateKey)"))
            {
                return;
            }
            
            var context = new CmdletContext();
            
            // allow for manipulation of parameters prior to loading into context
            PreExecutionContextLoad(context);
            
            #pragma warning disable CS0618, CS0612 //A class member was marked with the Obsolete attribute
            if (ParameterWasBound(nameof(this.Select)))
            {
                context.Select = CreateSelectDelegate(Select) ??
                    throw new System.ArgumentException("Invalid value for -Select parameter.", nameof(this.Select));
                if (this.PassThru.IsPresent)
                {
                    throw new System.ArgumentException("-PassThru cannot be used when -Select is specified.", nameof(this.Select));
                }
            }
            else if (this.PassThru.IsPresent)
            {
                context.Select = (response, cmdlet) => this.KeyId;
            }
            #pragma warning restore CS0618, CS0612 //A class member was marked with the Obsolete attribute
            context.BypassPolicyLockoutSafetyCheck = this.BypassPolicyLockoutSafetyCheck;
            context.Description = this.Description;
            context.KeyId = this.KeyId;
            #if MODULAR
            if (this.KeyId == null && ParameterWasBound(nameof(this.KeyId)))
            {
                WriteWarning("You are passing $null as a value for parameter KeyId which is marked as required. In case you believe this parameter was incorrectly marked as required, report this by opening an issue at https://github.com/aws/aws-tools-for-powershell/issues.");
            }
            #endif
            context.Policy = this.Policy;
            context.ReplicaRegion = this.ReplicaRegion;
            #if MODULAR
            if (this.ReplicaRegion == null && ParameterWasBound(nameof(this.ReplicaRegion)))
            {
                WriteWarning("You are passing $null as a value for parameter ReplicaRegion which is marked as required. In case you believe this parameter was incorrectly marked as required, report this by opening an issue at https://github.com/aws/aws-tools-for-powershell/issues.");
            }
            #endif
            if (this.Tag != null)
            {
                context.Tag = new List(this.Tag);
            }
            
            // allow further manipulation of loaded context prior to processing
            PostExecutionContextLoad(context);
            
            var output = Execute(context) as CmdletOutput;
            ProcessOutput(output);
        }
        
        #region IExecutor Members
        
        public object Execute(ExecutorContext context)
        {
            var cmdletContext = context as CmdletContext;
            // create request
            var request = new Amazon.KeyManagementService.Model.ReplicateKeyRequest();
            
            if (cmdletContext.BypassPolicyLockoutSafetyCheck != null)
            {
                request.BypassPolicyLockoutSafetyCheck = cmdletContext.BypassPolicyLockoutSafetyCheck.Value;
            }
            if (cmdletContext.Description != null)
            {
                request.Description = cmdletContext.Description;
            }
            if (cmdletContext.KeyId != null)
            {
                request.KeyId = cmdletContext.KeyId;
            }
            if (cmdletContext.Policy != null)
            {
                request.Policy = cmdletContext.Policy;
            }
            if (cmdletContext.ReplicaRegion != null)
            {
                request.ReplicaRegion = cmdletContext.ReplicaRegion;
            }
            if (cmdletContext.Tag != null)
            {
                request.Tags = cmdletContext.Tag;
            }
            
            CmdletOutput output;
            
            // issue call
            var client = Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint);
            try
            {
                var response = CallAWSServiceOperation(client, request);
                object pipelineOutput = null;
                pipelineOutput = cmdletContext.Select(response, this);
                output = new CmdletOutput
                {
                    PipelineOutput = pipelineOutput,
                    ServiceResponse = response
                };
            }
            catch (Exception e)
            {
                output = new CmdletOutput { ErrorResponse = e };
            }
            
            return output;
        }
        
        public ExecutorContext CreateContext()
        {
            return new CmdletContext();
        }
        
        #endregion
        
        #region AWS Service Operation Call
        
        private Amazon.KeyManagementService.Model.ReplicateKeyResponse CallAWSServiceOperation(IAmazonKeyManagementService client, Amazon.KeyManagementService.Model.ReplicateKeyRequest request)
        {
            Utils.Common.WriteVerboseEndpointMessage(this, client.Config, "AWS Key Management Service", "ReplicateKey");
            try
            {
                #if DESKTOP
                return client.ReplicateKey(request);
                #elif CORECLR
                return client.ReplicateKeyAsync(request).GetAwaiter().GetResult();
                #else
                        #error "Unknown build edition"
                #endif
            }
            catch (AmazonServiceException exc)
            {
                var webException = exc.InnerException as System.Net.WebException;
                if (webException != null)
                {
                    throw new Exception(Utils.Common.FormatNameResolutionFailureMessage(client.Config, webException.Message), webException);
                }
                throw;
            }
        }
        
        #endregion
        
        internal partial class CmdletContext : ExecutorContext
        {
            public System.Boolean? BypassPolicyLockoutSafetyCheck { get; set; }
            public System.String Description { get; set; }
            public System.String KeyId { get; set; }
            public System.String Policy { get; set; }
            public System.String ReplicaRegion { get; set; }
            public List Tag { get; set; }
            public System.Func Select { get; set; } =
                (response, cmdlet) => response;
        }
        
    }
}