using System;
using Renci.SshNet.Common;
using Renci.SshNet.NetConf;
using System.Xml;
using System.Diagnostics.CodeAnalysis;
namespace Renci.SshNet
{
    //  TODO:   Please help with documentation here, as I don't know the details, specially for the methods not documented.
    /// 
    /// Contains operation for working with NetConf server.
    /// 
    public partial class NetConfClient : BaseClient
    {
        /// 
        /// Holds  instance that used to communicate to the server
        /// 
        private NetConfSession _netConfSession;
        /// 
        /// Gets or sets the operation timeout.
        /// 
        /// 
        /// The timeout to wait until an operation completes. The default value is negative
        /// one (-1) milliseconds, which indicates an infinite time-out period.
        /// 
        public TimeSpan OperationTimeout { get; set; }
        #region Constructors
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The connection info.
        ///  is null.
        public NetConfClient(ConnectionInfo connectionInfo)
            : this(connectionInfo, false)
        {
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Connection host.
        /// Connection port.
        /// Authentication username.
        /// Authentication password.
        ///  is null.
        ///  is invalid, or  is null or contains whitespace characters.
        ///  is not within  and .
        [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
        public NetConfClient(string host, int port, string username, string password)
            : this(new PasswordConnectionInfo(host, port, username, password), true)
        {
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Connection host.
        /// Authentication username.
        /// Authentication password.
        ///  is null.
        ///  is invalid, or  is null or contains whitespace characters.
        public NetConfClient(string host, string username, string password)
            : this(host, ConnectionInfo.DEFAULT_PORT, username, password)
        {
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Connection host.
        /// Connection port.
        /// Authentication username.
        /// Authentication private key file(s) .
        ///  is null.
        ///  is invalid, -or-  is null or contains whitespace characters.
        ///  is not within  and .
        [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
        public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
            : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
        {
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Connection host.
        /// Authentication username.
        /// Authentication private key file(s) .
        ///  is null.
        ///  is invalid, -or-  is null or contains whitespace characters.
        public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles)
            : this(host, ConnectionInfo.DEFAULT_PORT, username, keyFiles)
        {
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The connection info.
        /// Specified whether this instance owns the connection info.
        ///  is null.
        /// 
        /// If  is true, then the
        /// connection info will be disposed when this instance is disposed.
        /// 
        private NetConfClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo)
            : base(connectionInfo, ownsConnectionInfo)
        {
            this.OperationTimeout = new TimeSpan(0, 0, 0, 0, -1);
            this.AutomaticMessageIdHandling = true;
        }
        #endregion
        /// 
        /// Gets NetConf server capabilities.
        /// 
        /// Client is not connected.
        public XmlDocument ServerCapabilities 
        {
            get { return this._netConfSession.ServerCapabilities; }
        }
        /// 
        /// Gets NetConf client capabilities.
        /// 
        /// Client is not connected.
        public XmlDocument ClientCapabilities
        {
            get { return this._netConfSession.ClientCapabilities; }
        }
        /// 
        /// Gets or sets a value indicating whether automatic message id handling is
        /// enabled.
        /// 
        /// 
        /// true if automatic message id handling is enabled; otherwise, false.
        /// The default value is true.
        /// 
        public bool AutomaticMessageIdHandling { get; set; }
        /// 
        /// Sends the receive RPC.
        /// 
        /// The RPC.
        /// Reply message to RPC request
        /// Client is not connected.
        public XmlDocument SendReceiveRpc(XmlDocument rpc)
        {
            return this._netConfSession.SendReceiveRpc(rpc, this.AutomaticMessageIdHandling);
        }
        /// 
        /// Sends the receive RPC.
        /// 
        /// The XML.
        /// Reply message to RPC request
        public XmlDocument SendReceiveRpc(string xml)
        {
            var rpc = new XmlDocument();
            rpc.LoadXml(xml);
            return SendReceiveRpc(rpc);
        }
        /// 
        /// Sends the close RPC.
        /// 
        /// Reply message to closing RPC request
        /// Client is not connected.
        public XmlDocument SendCloseRpc()
        {
            var rpc = new XmlDocument();
            rpc.LoadXml("");
            return this._netConfSession.SendReceiveRpc(rpc, this.AutomaticMessageIdHandling);
        }
        /// 
        /// Called when client is connected to the server.
        /// 
        protected override void OnConnected()
        {
            base.OnConnected();
            this._netConfSession = new NetConfSession(this.Session, this.OperationTimeout);
            this._netConfSession.Connect();
        }
        /// 
        /// Called when client is disconnecting from the server.
        /// 
        protected override void OnDisconnecting()
        {
            base.OnDisconnecting();
            this._netConfSession.Disconnect();
        }
        /// 
        /// Releases unmanaged and - optionally - managed resources
        /// 
        /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
        protected override void Dispose(bool disposing)
        {
            if (this._netConfSession != null)
            {
                this._netConfSession.Dispose();
                this._netConfSession = null;
            }
            base.Dispose(disposing);
        }
    }
}