using FellowOakDicom.Network;
using FellowOakDicom;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using IRaCIS.Core.Application.Contracts.Dicom;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace IRaCIS.Core.Application.Service.ImageAndDoc
{
    /// <summary>
    /// 后台托管服务的方式运行
    /// </summary>
    //public class CStoreSCPHostedService : IHostedService
    //{
    //    private readonly ILogger<CStoreSCPHostedService> _logger;
    //    private readonly IDicomServerFactory _dicomServerFactory;
    //    private IDicomServer? _server;

    //    public CStoreSCPHostedService(ILogger<CStoreSCPHostedService> logger, IDicomServerFactory dicomServerFactory)
    //    {
    //        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    //        _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory));
    //    }

    //    public async Task StartAsync(CancellationToken cancellationToken)
    //    {
    //        _logger.LogInformation("Starting DICOM server");
    //        _server = _dicomServerFactory.Create<CStoreSCPService>(104);
    //        _logger.LogInformation("DICOM server is running");
    //    }

    //    public Task StopAsync(CancellationToken cancellationToken)
    //    {
    //        if (_server != null)
    //        {
    //            _server.Stop();
    //            _server.Dispose();
    //            _server = null;
    //        }
    //        return Task.CompletedTask;
    //    }
    //}


    public class CStoreSCPService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCEchoProvider
    {
        private  IServiceProvider _serviceProvider { get; set; }


        private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[]
        {
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
        };

        private static readonly DicomTransferSyntax[] _acceptedImageTransferSyntaxes = new DicomTransferSyntax[]
        {
               // Lossless
               DicomTransferSyntax.JPEGLSLossless,
               DicomTransferSyntax.JPEG2000Lossless,
               DicomTransferSyntax.JPEGProcess14SV1,
               DicomTransferSyntax.JPEGProcess14,
               DicomTransferSyntax.RLELossless,
               // Lossy
               DicomTransferSyntax.JPEGLSNearLossless,
               DicomTransferSyntax.JPEG2000Lossy,
               DicomTransferSyntax.JPEGProcess1,
               DicomTransferSyntax.JPEGProcess2_4,
               // Uncompressed
               DicomTransferSyntax.ExplicitVRLittleEndian,
               DicomTransferSyntax.ExplicitVRBigEndian,
               DicomTransferSyntax.ImplicitVRLittleEndian
        };


        public CStoreSCPService(INetworkStream stream, Encoding fallbackEncoding, ILogger log, DicomServiceDependencies dependencies)
            : base(stream, fallbackEncoding, log, dependencies)
        {
            var tt = base.UserState;
            //_dicomArchiveService = dicomArchiveService;
        }




        public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
        {
            _serviceProvider =(IServiceProvider) this.UserState;

            if (association.CalledAE != "STORESCP")
            {
                return SendAssociationRejectAsync(
                    DicomRejectResult.Permanent,
                    DicomRejectSource.ServiceUser,
                    DicomRejectReason.CalledAENotRecognized);
            }

            foreach (var pc in association.PresentationContexts)
            {
                if (pc.AbstractSyntax == DicomUID.Verification)
                {
                    pc.AcceptTransferSyntaxes(_acceptedTransferSyntaxes);
                }
                else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None)
                {
                    pc.AcceptTransferSyntaxes(_acceptedImageTransferSyntaxes);
                }
            }

            return SendAssociationAcceptAsync(association);
        }


        public Task OnReceiveAssociationReleaseRequestAsync()
        {
            return SendAssociationReleaseResponseAsync();
        }


        public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
        {
            /* nothing to do here */
        }


        public void OnConnectionClosed(Exception exception)
        {
            /* nothing to do here */
        }


        public async Task<DicomCStoreResponse> OnCStoreRequestAsync(DicomCStoreRequest request)
        {
           var tt= _serviceProvider.GetService<IDicomArchiveService>();

            var studyUid = request.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID).Trim();
            var instUid = request.SOPInstanceUID.UID;

            var path = Path.GetFullPath(@".\DICOM-Store");

            path = Path.Combine(path, studyUid);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            path = Path.Combine(path, instUid) + ".dcm";

            await request.File.SaveAsync(path);

            return new DicomCStoreResponse(request, DicomStatus.Success);
        }


        public Task OnCStoreRequestExceptionAsync(string tempFileName, Exception e)
        {
            // let library handle logging and error response
            return Task.CompletedTask;
        }


        public Task<DicomCEchoResponse> OnCEchoRequestAsync(DicomCEchoRequest request)
        {
            return Task.FromResult(new DicomCEchoResponse(request, DicomStatus.Success));
        }

    }
}
