// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.messaging.servicebus.administration.models;

import com.azure.core.annotation.Fluent;
import com.azure.messaging.servicebus.administration.ServiceBusAdministrationAsyncClient;
import com.azure.messaging.servicebus.administration.ServiceBusAdministrationClient;
import com.azure.messaging.servicebus.administration.implementation.EntityHelper;
import com.azure.messaging.servicebus.administration.implementation.models.AuthorizationRuleImpl;
import com.azure.messaging.servicebus.administration.implementation.models.MessageCountDetailsImpl;
import com.azure.messaging.servicebus.administration.implementation.models.QueueDescriptionImpl;

import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.stream.Collectors;

import static com.azure.messaging.servicebus.implementation.MessageUtils.toPrimitive;

/**
 * Properties on a queue.
 *
 * @see ServiceBusAdministrationAsyncClient#getQueue(String)
 * @see ServiceBusAdministrationClient#getQueue(String)
 */
@Fluent
public final class QueueProperties {
    private final QueueDescriptionImpl description;
    private final List<AuthorizationRule> authorizationRules;
    private String queueName;

    static {
        // This is used by classes in different packages to get access to private and package-private methods.
        EntityHelper.setQueueAccessor(new EntityHelper.QueueAccessor() {
            @Override
            public QueueDescriptionImpl toImplementation(QueueProperties queue, List<AuthorizationRuleImpl> rules) {
                final QueueDescriptionImpl description = new QueueDescriptionImpl()
                    .setAccessedAt(queue.getAccessedAt())
                    .setAutoDeleteOnIdle(queue.getAutoDeleteOnIdle())
                    .setCreatedAt(queue.getCreatedAt())
                    .setDeadLetteringOnMessageExpiration(queue.isDeadLetteringOnMessageExpiration())
                    .setDefaultMessageTimeToLive(queue.getDefaultMessageTimeToLive())
                    .setDuplicateDetectionHistoryTimeWindow(queue.getDuplicateDetectionHistoryTimeWindow())
                    .setEnablePartitioning(queue.isPartitioningEnabled())
                    .setEnableExpress(queue.description.isEnableExpress())
                    .setEnableBatchedOperations(queue.description.isEnableBatchedOperations())
                    .setEntityAvailabilityStatus(queue.description.getEntityAvailabilityStatus())
                    .setForwardTo(queue.getForwardTo())
                    .setForwardDeadLetteredMessagesTo(queue.getForwardDeadLetteredMessagesTo())
                    .setIsAnonymousAccessible(queue.description.isAnonymousAccessible())
                    .setLockDuration(queue.getLockDuration())
                    .setMaxSizeInMegabytes(queue.getMaxSizeInMegabytes())
                    .setMaxDeliveryCount(queue.getMaxDeliveryCount())
                    .setMessageCount(queue.description.getMessageCount())
                    .setMessageCountDetails(queue.getMessageCountDetails())
                    .setSupportOrdering(queue.description.isSupportOrdering())
                    .setStatus(queue.getStatus())
                    .setSizeInBytes(queue.getSizeInBytes())
                    .setRequiresSession(queue.isSessionRequired())
                    .setRequiresDuplicateDetection(queue.isDuplicateDetectionRequired())
                    .setUpdatedAt(queue.getUpdatedAt())
                    .setUserMetadata(queue.getUserMetadata());

                if (!rules.isEmpty()) {
                    description.setAuthorizationRules(rules);
                }
                if (queue.getMaxMessageSizeInKilobytes() != 0) {
                    description.setMaxMessageSizeInKilobytes(queue.getMaxMessageSizeInKilobytes());
                }

                return description;
            }

            @Override
            public QueueProperties toModel(QueueDescriptionImpl queueDescription) {
                return new QueueProperties(queueDescription);
            }

            @Override
            public void setName(QueueProperties queueProperties, String name) {
                queueProperties.queueName = name;
            }
        });
    }

    /**
     * Creates a queue using a {@link QueueDescriptionImpl}.
     *
     * @param description The queue to use.
     */
    QueueProperties(QueueDescriptionImpl description) {
        this.description = description;
        this.authorizationRules = description.getAuthorizationRules().stream()
            .map(SharedAccessAuthorizationRule::new)
            .collect(Collectors.toList());
    }

    /**
     * Gets the name of the queue.
     *
     * @return The name of the queue.
     */
    public String getName() {
        return queueName;
    }

    /**
     * Get the autoDeleteOnIdle property: ISO 8601 timeSpan idle interval after which the queue is automatically
     * deleted. The minimum duration is 5 minutes.
     *
     * @return the autoDeleteOnIdle value.
     */
    public Duration getAutoDeleteOnIdle() {
        return description.getAutoDeleteOnIdle();
    }

    /**
     * Set the autoDeleteOnIdle property: ISO 8601 timeSpan idle interval after which the queue is automatically
     * deleted. The minimum duration is 5 minutes.
     *
     * @param autoDeleteOnIdle the autoDeleteOnIdle value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setAutoDeleteOnIdle(Duration autoDeleteOnIdle) {
        description.setAutoDeleteOnIdle(autoDeleteOnIdle);
        return this;
    }

    /**
     * Get the authorizationRules property: Authorization rules for resource.
     *
     * @return the authorizationRules value.
     */
    public List<AuthorizationRule> getAuthorizationRules() {
        return this.authorizationRules;
    }

    /**
     * Get the defaultMessageTimeToLive property: ISO 8601 default message timespan to live value. This is the duration
     * after which the message expires, starting from when the message is sent to Service Bus. This is the default value
     * used when TimeToLive is not set on a message itself.
     *
     * @return the defaultMessageTimeToLive value.
     */
    public Duration getDefaultMessageTimeToLive() {
        return description.getDefaultMessageTimeToLive();
    }

    /**
     * Set the defaultMessageTimeToLive property: ISO 8601 default message timespan to live value. This is the duration
     * after which the message expires, starting from when the message is sent to Service Bus. This is the default value
     * used when TimeToLive is not set on a message itself.
     *
     * @param defaultMessageTimeToLive the defaultMessageTimeToLive value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setDefaultMessageTimeToLive(Duration defaultMessageTimeToLive) {
        description.setDefaultMessageTimeToLive(defaultMessageTimeToLive);
        return this;
    }

    /**
     * Get the deadLetteringOnMessageExpiration property: A value that indicates whether this queue has dead letter
     * support when a message expires.
     *
     * @return the deadLetteringOnMessageExpiration value.
     */
    public boolean isDeadLetteringOnMessageExpiration() {
        return toPrimitive(description.isDeadLetteringOnMessageExpiration());
    }

    /**
     * Set the deadLetteringOnMessageExpiration property: A value that indicates whether this queue has dead letter
     * support when a message expires.
     *
     * @param deadLetteringOnMessageExpiration the deadLetteringOnMessageExpiration value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setDeadLetteringOnMessageExpiration(boolean deadLetteringOnMessageExpiration) {
        description.setDeadLetteringOnMessageExpiration(deadLetteringOnMessageExpiration);
        return this;
    }

    /**
     * Get the duplicateDetectionHistoryTimeWindow property: ISO 8601 timeSpan structure that defines the duration of
     * the duplicate detection history. The default value is 10 minutes.
     *
     * @return the duplicateDetectionHistoryTimeWindow value.
     */
    public Duration getDuplicateDetectionHistoryTimeWindow() {
        return description.getDuplicateDetectionHistoryTimeWindow();
    }

    /**
     * Set the duplicateDetectionHistoryTimeWindow property: ISO 8601 timeSpan structure that defines the duration of
     * the duplicate detection history. The default value is 10 minutes.
     *
     * @param duplicateDetectionHistoryTimeWindow the duplicateDetectionHistoryTimeWindow value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setDuplicateDetectionHistoryTimeWindow(Duration duplicateDetectionHistoryTimeWindow) {
        description.setDuplicateDetectionHistoryTimeWindow(duplicateDetectionHistoryTimeWindow);
        return this;
    }

    /**
     * Get the enableBatchedOperations property: Value that indicates whether server-side batched operations are
     * enabled.
     *
     * @return the enableBatchedOperations value.
     */
    public boolean isBatchedOperationsEnabled() {
        return toPrimitive(description.isEnableBatchedOperations());
    }

    /**
     * Set the enableBatchedOperations property: Value that indicates whether server-side batched operations are
     * enabled.
     *
     * @param enableBatchedOperations the enableBatchedOperations value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setBatchedOperationsEnabled(boolean enableBatchedOperations) {
        description.setEnableBatchedOperations(enableBatchedOperations);
        return this;
    }

    /**
     * Get the enablePartitioning property: A value that indicates whether the queue is to be partitioned across
     * multiple message brokers.
     *
     * @return the enablePartitioning value.
     */
    public boolean isPartitioningEnabled() {
        return toPrimitive(description.isEnablePartitioning());
    }

    /**
     * Get the forwardTo property: The name of the recipient entity to which all the messages sent to the queue are
     * forwarded to.
     *
     * @return the forwardTo value.
     */
    public String getForwardTo() {
        return description.getForwardTo();
    }

    /**
     * Set the forwardTo property: The name of the recipient entity to which all the messages sent to the queue are
     * forwarded to.
     *
     * @param forwardTo the forwardTo value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setForwardTo(String forwardTo) {
        description.setForwardTo(forwardTo);
        return this;
    }

    /**
     * Get the forwardDeadLetteredMessagesTo property: The name of the recipient entity to which all the dead-lettered
     * messages of this queue are forwarded to.
     *
     * @return the forwardDeadLetteredMessagesTo value.
     */
    public String getForwardDeadLetteredMessagesTo() {
        return description.getForwardDeadLetteredMessagesTo();
    }

    /**
     * Set the forwardDeadLetteredMessagesTo property: The name of the recipient entity to which all the dead-lettered
     * messages of this queue are forwarded to.
     *
     * @param forwardDeadLetteredMessagesTo the forwardDeadLetteredMessagesTo value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setForwardDeadLetteredMessagesTo(String forwardDeadLetteredMessagesTo) {
        description.setForwardDeadLetteredMessagesTo(forwardDeadLetteredMessagesTo);
        return this;
    }

    /**
     * Get the lockDuration property: ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the
     * message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1
     * minute.
     *
     * @return the lockDuration value.
     */
    public Duration getLockDuration() {
        return description.getLockDuration();
    }

    /**
     * Set the lockDuration property: ISO 8601 timespan duration of a peek-lock; that is, the amount of time that the
     * message is locked for other receivers. The maximum value for LockDuration is 5 minutes; the default value is 1
     * minute.
     *
     * @param lockDuration the lockDuration value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setLockDuration(Duration lockDuration) {
        description.setLockDuration(lockDuration);
        return this;
    }

    /**
     * Get the maxDeliveryCount property: The maximum delivery count. A message is automatically dead-lettered after
     * this number of deliveries. Default value is 10.
     *
     * @return the maxDeliveryCount value.
     */
    public int getMaxDeliveryCount() {
        return toPrimitive(description.getMaxDeliveryCount());
    }

    /**
     * Sets the maximum delivery count. A message is automatically dead-lettered after
     * this number of deliveries. Default value is 10.
     *
     * @param maxDeliveryCount the maxDeliveryCount value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setMaxDeliveryCount(Integer maxDeliveryCount) {
        description.setMaxDeliveryCount(maxDeliveryCount);
        return this;
    }

    /**
     * Gets the maximum size of the queue in megabytes, which is the size of memory allocated for the queue.
     *
     * @return the maxSizeInMegabytes value.
     */
    public long getMaxSizeInMegabytes() {
        return toPrimitive(description.getMaxSizeInMegabytes());
    }

    /**
     * Set the maxSizeInMegabytes property: The maximum size of the queue in megabytes, which is the size of memory
     * allocated for the queue.
     *
     * @param maxSizeInMegabytes the maxSizeInMegabytes value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setMaxSizeInMegabytes(Integer maxSizeInMegabytes) {
        description.setMaxSizeInMegabytes(maxSizeInMegabytes == null ? null : (long) maxSizeInMegabytes);
        return this;
    }

    /**
     * Get the requiresDuplicateDetection property: A value indicating if this queue requires duplicate detection.
     *
     * @return the requiresDuplicateDetection value.
     */
    public boolean isDuplicateDetectionRequired() {
        return toPrimitive(description.isRequiresDuplicateDetection());
    }

    /**
     * Get the requiresSession property: A value that indicates whether the queue supports the concept of sessions.
     *
     * @return the requiresSession value.
     */
    public boolean isSessionRequired() {
        return toPrimitive(description.isRequiresSession());
    }

    /**
     * Get the status property: Status of a Service Bus resource.
     *
     * @return the status value.
     */
    public EntityStatus getStatus() {
        return description.getStatus();
    }

    /**
     * Set the status property: Status of a Service Bus resource.
     *
     * @param status the status value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setStatus(EntityStatus status) {
        description.setStatus(status);
        return this;
    }

    /**
     * Get the userMetadata property: Custom metdata that user can associate with the description. Max length is 1024
     * chars.
     *
     * @return the userMetadata value.
     */
    public String getUserMetadata() {
        return description.getUserMetadata();
    }

    /**
     * Set the userMetadata property: Custom metdata that user can associate with the description. Max length is 1024
     * chars.
     *
     * @param userMetadata the userMetadata value to set.
     *
     * @return the {@link QueueProperties} object itself.
     */
    public QueueProperties setUserMetadata(String userMetadata) {
        description.setUserMetadata(userMetadata);
        return this;
    }

    /**
     * Get the maxMessageSizeInKilobytes property: The maximum size of a message in kilobytes.
     *
     * @return the maxMessageSizeInKilobytes value.
     */
    public long getMaxMessageSizeInKilobytes() {
        return toPrimitive(description.getMaxMessageSizeInKilobytes());
    }

    /**
     * Set the maxMessageSizeInKilobytes property: The maximum size of a message in kilobytes.
     *
     * @param maxMessageSizeInKilobytes the maxMessageSizeInKilobytes value to set.
     * @return the QueueDescription object itself.
     */
    public QueueProperties setMaxMessageSizeInKilobytes(long maxMessageSizeInKilobytes) {
        description.setMaxMessageSizeInKilobytes(maxMessageSizeInKilobytes);
        return this;
    }

    /**
     * Get the accessedAt property: Last time a message was sent, or the last time there was a receive request to this
     * queue.
     *
     * @return the accessedAt value.
     */
    OffsetDateTime getAccessedAt() {
        return description.getAccessedAt();
    }

    /**
     * Get the createdAt property: The exact time the queue was created.
     *
     * @return the createdAt value.
     */
    OffsetDateTime getCreatedAt() {
        return description.getCreatedAt();
    }

    /**
     * Get the messageCount property: The number of messages in the queue.
     *
     * @return the messageCount value.
     */
    Integer getMessageCount() {
        return description.getMessageCount();
    }

    /**
     * Get the messageCountDetails property: Details about the message counts in entity.
     *
     * @return the messageCountDetails value.
     */
    MessageCountDetailsImpl getMessageCountDetails() {
        return description.getMessageCountDetails();
    }

    /**
     * Get the sizeInBytes property: The size of the queue, in bytes.
     *
     * @return the sizeInBytes value.
     */
    Long getSizeInBytes() {
        return description.getSizeInBytes();
    }

    /**
     * Get the updatedAt property: The exact time the entity description was last updated.
     *
     * @return the updatedAt value.
     */
    OffsetDateTime getUpdatedAt() {
        return description.getUpdatedAt();
    }

    QueueProperties setPartitioningEnabled(boolean enablePartitioning) {
        description.setEnablePartitioning(enablePartitioning);
        return this;
    }

    QueueProperties setDuplicateDetectionRequired(boolean requiresDuplicateDetection) {
        description.setRequiresDuplicateDetection(requiresDuplicateDetection);
        return this;
    }

    QueueProperties setSessionRequired(boolean requiresSession) {
        description.setRequiresSession(requiresSession);
        return this;
    }
}
