using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Net;
using System.Threading.Tasks;
using BO.AppServer.Metadata.Dto;
using BO.AppServer.Metadata.Enums;
using BO.ProcessServer.Business.Enums;
using BO.ProcessServer.Options;
using Connector.PS;
using Quadarax.Foundation.Core.Object;

namespace BO.ProcessServer.Business
{
    internal class Connector : DisposableObject, IConnectionPS
    {

        #region *** Private fields ***
        private IConnectionPS _connection;
        #endregion

        #region *** Properties ***
        public bool IsOpen => _connection?.IsOpen ?? false;
        #endregion

        #region *** Constructor ***
        public Connector(Configuration configuration, IFileSystem fileSystem)
        {
            if (configuration.System.Mode == AppModeEnum.Proxy || configuration.System.Mode == AppModeEnum.ProxyApp)
                _connection = new ConnectionProxy(configuration, fileSystem);
            else
                _connection = new Connection(configuration.ApiBaseUrl, configuration.ApiTimeout,
                    configuration.System.Identification, IPAddress.Parse(configuration.System.PreferredInterface),
                    configuration.System.PoolPullDocuments);
        }
        #endregion

        #region *** Public Operations ***
        public async Task<IEnumerable<DocumentRDto>> GetDocumentsAsync(DocumentsScopeEnums scope)
        {
            return await _connection?.GetDocumentsAsync(scope)!;
        }

        public async Task<DocumentStatusEnum> GetDocumentStateAsync(long documentId)
        {
            return await _connection?.GetDocumentStateAsync(documentId)!;
        }

        public async Task<DocumentRDto> GetDocumentInfoAsync(long documentId)
        {
            return await _connection?.GetDocumentInfoAsync(documentId)!;
        }

        public async Task<DocumentStatusEnum> SetDocumentStateAsync(long documentId, DocumentStatusEnum status)
        {
            return await _connection?.SetDocumentStateAsync(documentId, status)!;
        }

        public async Task<Stream> GetDocumentContentAsync(long documentId, long artifactId)
        {
            return await _connection?.GetDocumentContentAsync(documentId, artifactId)!;
        }

        public async Task<ArtifactRDto> SetDocumentContentAsync(long documentId, string fileName, string mimeType, bool overwriteIfExists,
            Stream contentStream)
        {
            return await _connection?.SetDocumentContentAsync(documentId, fileName, mimeType, overwriteIfExists, contentStream)!;
        }

        public void Open(string userName, string userPassword, string magicKey)
        {
            _connection?.Open(userName, userPassword, magicKey);
        }

        public void Close()
        {
            _connection?.Close();
        }

        public bool Ping(out TimeSpan duration, out string status)
        {
            return _connection.Ping(out duration,out status);
        }

        #endregion

        #region *** Private Operations & Overrides ***
        protected override void OnDisposing()
        {
            _connection?.Dispose();
            _connection = null;
        }

        #endregion
        
        
    }
}
