/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License 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.
 */

// DO NOT EDIT IT MANUALLY. This file is generated by opendal/dev/src/generate/dotnet.rs.

using OpenDAL.ServiceConfig.Abstractions;

namespace OpenDAL.ServiceConfig
{
    /// <summary>
    /// Configuration for service webdav.
    /// </summary>
    public sealed class WebdavServiceConfig : IServiceConfig
    {
        /// <summary>
        /// Deprecated: WebDAV copy capability is enabled by default.
        /// </summary>
        [System.Obsolete("WebDAV copy capability is enabled by default and this option is no longer needed.")]
        public bool? DisableCopy { get; init; }
        /// <summary>
        /// Disable automatic parent directory creation before write operations. By default, OpenDAL creates parent directories using MKCOL before writing files. This requires PROPFIND support to check directory existence. Some WebDAV-compatible servers (e.g., bazel-remote) don't support PROPFIND or don't require explicit directory creation. Enable this option to skip the MKCOL calls and write files directly. Default: false
        /// </summary>
        public bool? DisableCreateDir { get; init; }
        /// <summary>
        /// Enable conditional read support. When enabled (the default), OpenDAL forwards the RFC 7232 headers `If-Match`, `If-None-Match`, `If-Modified-Since` and `If-Unmodified-Since` to the server when callers provide them. Some WebDAV-compatible servers (e.g., nginx-dav) don't return ETags in PROPFIND or don't honor these headers on GET. Setting this to `false` drops the four `read_with_if_*` capabilities, so calls like `reader_with(path).if_match(...)` return `ErrorKind::Unsupported` locally instead of being silently ignored by the server. Default: true
        /// </summary>
        public bool? EnableConditionalRead { get; init; }
        /// <summary>
        /// Deprecated: WebDAV user metadata capability is enabled by default.
        /// </summary>
        [System.Obsolete("WebDAV user metadata capability is enabled by default. Use CapabilityOverrideLayer to override write_with_user_metadata for endpoints without PROPPATCH support.")]
        public bool? EnableUserMetadata { get; init; }
        /// <summary>
        /// endpoint of this backend
        /// </summary>
        public string? Endpoint { get; init; }
        /// <summary>
        /// password of this backend
        /// </summary>
        public string? Password { get; init; }
        /// <summary>
        /// root of this backend
        /// </summary>
        public string? Root { get; init; }
        /// <summary>
        /// token of this backend
        /// </summary>
        public string? Token { get; init; }
        /// <summary>
        /// The XML namespace prefix for user metadata properties. This prefix is used in PROPPATCH/PROPFIND XML requests. Different servers may require different prefixes. Default: "opendal"
        /// </summary>
        public string? UserMetadataPrefix { get; init; }
        /// <summary>
        /// The XML namespace URI for user metadata properties. This URI uniquely identifies the namespace for custom properties. Different servers may require different namespace URIs. For example, Nextcloud might work better with its own namespace. Default: `https://opendal.apache.org/ns`
        /// </summary>
        public string? UserMetadataUri { get; init; }
        /// <summary>
        /// username of this backend
        /// </summary>
        public string? Username { get; init; }

        public string Scheme => "webdav";

        public IReadOnlyDictionary<string, string> ToOptions()
        {
            var map = new Dictionary<string, string>();
#pragma warning disable CS0618
            if (DisableCopy is not null)
            {
                map["disable_copy"] = Utilities.ToOptionString(DisableCopy);
            }
#pragma warning restore CS0618
            if (DisableCreateDir is not null)
            {
                map["disable_create_dir"] = Utilities.ToOptionString(DisableCreateDir);
            }
            if (EnableConditionalRead is not null)
            {
                map["enable_conditional_read"] = Utilities.ToOptionString(EnableConditionalRead);
            }
#pragma warning disable CS0618
            if (EnableUserMetadata is not null)
            {
                map["enable_user_metadata"] = Utilities.ToOptionString(EnableUserMetadata);
            }
#pragma warning restore CS0618
            if (Endpoint is not null)
            {
                map["endpoint"] = Utilities.ToOptionString(Endpoint);
            }
            if (Password is not null)
            {
                map["password"] = Utilities.ToOptionString(Password);
            }
            if (Root is not null)
            {
                map["root"] = Utilities.ToOptionString(Root);
            }
            if (Token is not null)
            {
                map["token"] = Utilities.ToOptionString(Token);
            }
            if (UserMetadataPrefix is not null)
            {
                map["user_metadata_prefix"] = Utilities.ToOptionString(UserMetadataPrefix);
            }
            if (UserMetadataUri is not null)
            {
                map["user_metadata_uri"] = Utilities.ToOptionString(UserMetadataUri);
            }
            if (Username is not null)
            {
                map["username"] = Utilities.ToOptionString(Username);
            }
            return map;
        }
    }

}
