using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Http;
using FMSAdmin.Models;
using FMSAdmin.Entities;
using System.Drawing;
using System.Drawing.Imaging;
using SelectPdf;

namespace FMSAdmin.Helpers {
    public class StorageHelper {
        private readonly AppSettings _appSettings;
        private readonly ILogger<StorageHelper> _logger;

        public StorageHelper(
            IOptions<AppSettings> appSettings,
            ILogger<StorageHelper> logger
            ) {
            _appSettings = appSettings.Value;
            _logger = logger;

            var currentDir = _appSettings.StoragePath;

            // 초기 디렉토리 생성 - 추후 프로그램 초기화 부분으로..
            Directory.CreateDirectory(currentDir + "/wwwroot/files");
            Directory.CreateDirectory(currentDir + "/wwwroot/files/temp");
            Directory.CreateDirectory(currentDir + "/wwwroot/files/editor");
        }

        public bool DirectoryExists(string path) {
            return Directory.Exists(_LocalPath(path));
        }

        public bool FileExists(string path) {
            return File.Exists(_LocalPath(path));
        }

        public string ReadAllText(string path) {
            return File.ReadAllText(_LocalPath(path));
        }

        public void WriteAllText(string path, string text) {
            File.WriteAllText(_LocalPath(path), text);
        }

        public void CreateDirectory(string path) {
            var localPath = _LocalPath(path);

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

        public UploadFile Save(string path, IFormFile file) {
            var filePath = $"{path}";
            filePath = filePath.Replace("//", "/");

            var localPath = _LocalPath(filePath);
            string fullUrl = _FullUrl(filePath);

            if (file.Length > 0) {
                using (var stream = new FileStream(localPath, FileMode.Create)) {
                    file.CopyTo(stream);
                }
            }
            return new UploadFile {
                Name = file.FileName,
                FileSize = file.Length,
                ContentType = file.ContentType,
                Path = filePath,
                Url = fullUrl
            };
        }

        private bool Compress(string path, Stream stream) {
            bool isCompress = false;
            Image image = null;
            try { image = Image.FromStream(stream); } catch { }
            if (image != null) {
                var jpgEncoder = ImageCodecInfo.GetImageDecoders().Where(x => x.FormatID == ImageFormat.Jpeg.Guid).FirstOrDefault();
                if (jpgEncoder != null) {
                    try {
                        var encoderParameters = new EncoderParameters(1);
                        encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 75L);
                        image.Save(path, jpgEncoder, encoderParameters);
                        isCompress = true;
                    } catch { }
                }
            }

            return isCompress;
        }

        public UploadFile SaveImage(string path, IFormFile file) {
            var filePath = $"{path}";
            filePath = filePath.Replace("//", "/");

            var localPath = _LocalPath(filePath);
            string fullUrl = _FullUrl(filePath);

            if (file.Length > 0) {
                bool isCompress = false;
                using (var stream = file.OpenReadStream()) {
                    isCompress = Compress(localPath, stream);
                }

                if (!isCompress) {
                    using (var stream = new FileStream(localPath, FileMode.Create)) {
                        file.CopyTo(stream);
                    }
                }
            }
            return new UploadFile {
                Name = file.FileName,
                FileSize = file.Length,
                ContentType = file.ContentType,
                Path = filePath,
                Url = fullUrl
            };
        }

        public void Copy(string src, string dst) {
            var srcPath = _LocalPath(src);
            var dstPath = _LocalPath(dst);

            _logger.LogInformation("copy " + srcPath + " to " + dstPath);
            File.Copy(srcPath, dstPath, true);
        }

        public void Move(string src, string dst) {
            var srcPath = _LocalPath(src);
            var dstPath = _LocalPath(dst);

            _logger.LogInformation("move " + srcPath + " to " + dstPath);
            File.Move(srcPath, dstPath, true);
        }

        public void DeleteTempFiles(double oldDay = 1) {
            var tempDir = _LocalPath("/temp");
            // 파일
            foreach (var file in Directory.GetFiles(tempDir)) {
                var created = File.GetCreationTime(file);
                if ((DateTime.Now - created).TotalDays > oldDay) {
                    File.Delete(file);
                    //_logger.LogInformation("delete file " + file);
                }
            }
            // 폴더
            foreach (var dir in Directory.GetDirectories(tempDir)) {
                var created = Directory.GetCreationTime(dir);
                if ((DateTime.Now - created).TotalDays > oldDay) {
                    Directory.Delete(dir, true);
                    //_logger.LogInformation("delete directory " + dir);
                }
            }
        }

        public UploadFile SaveTemp(IFormFile file) {
            var ext = Path.GetExtension(file.FileName);
            var name = Path.GetFileNameWithoutExtension(Path.GetRandomFileName());
            var filename = $"{name}{ext}";
            return Save($"/temp/{filename}", file);
        }

        public UploadFile SaveTempImage(IFormFile file) {
            var ext = Path.GetExtension(file.FileName);
            var name = Path.GetFileNameWithoutExtension(Path.GetRandomFileName());
            var filename = $"{name}{ext}";
            return SaveImage($"/temp/{filename}", file);
        }

        public void CopyEntity(string temp, CmFile file) {
            if (file == null) return;
            if (file.FileCategory == null) return;

            var entity = file.FileCategoryId;
            var ext = Path.GetExtension(file.Name);
            var filename = $"{file.FileId}{ext}";

            var currentDir = _appSettings.StoragePath;
            Directory.CreateDirectory(currentDir + "/wwwroot/files/" + entity);

            Copy(temp, $"/{entity}/{filename}");
        }

        public object ParseFile(CmFile file) {
            if (file == null) return null;

            var ext = Path.GetExtension(file.Name);
            file.Path = $"/{file.FileCategoryId}/{file.FileId}{ext}";
            file.Url = _FullUrl(file.Path);
            return new {
                file.FileId,
                file.Name,
                file.FileCategoryId,
                file.FileSize,
                file.ContentType,
                file.Path,
                file.Url,
            };
        }

        public string ParseFileUrl(CmFile file) {
            if (file == null) return null;

            var ext = Path.GetExtension(file.Name);
            file.Path = $"/{file.FileCategoryId}/{file.FileId}{ext}";
            file.Url = _FullUrl(file.Path);
            return file.Url;
        }

        public string getFilePath(CmFile file) {
            if (file == null) return null;

            var ext = Path.GetExtension(file.Name);
            return $"/{file.FileCategoryId}/{file.FileId}{ext}";
        }
        public void CopyGroup(string temp, string group, string file) {
            if (string.IsNullOrEmpty(group)) return;
            if (string.IsNullOrEmpty(file)) return;

            group = group.ToLower();
            CreateDirectory("/" + group);

            Copy(temp, $"/{group}/{file}");
        }

        public FileStream GetFileStream(string path) {
            return File.OpenRead(_LocalPath(path));
        }

        public String GetLocalPath(string path) {
            return _LocalPath(path);
        }

        public String GetFullUrl(string path) {
            return _FullUrl(path);
        }

        private string _LocalPath(string path) {
            var currentDir = _appSettings.StoragePath;
            var basePath = "/files";
            var filePath = $"{path}";
            filePath = filePath.Replace("//", "/");
            var localPath = $"{currentDir}/wwwroot/{basePath}/{filePath}";
            localPath = localPath.Replace("//", "/");
            return localPath;
        }

        private string _FullUrl(string path) {
            var basePath = "/files";
            string fullUrl = $"{_appSettings.StorageUrl}{basePath}{path}";
            return fullUrl;
        }

        public void PdfConvertImage(CmFile pdf) {
            var ext = Path.GetExtension(pdf.Name);
            if (ext == ".pdf") {
                SelectPdf.GlobalProperties.LicenseKey = "nrWvvqyrr76nqKq+rK6wrr6tr7CvrLCnp6en";

                PdfRasterizer rasterizer = new PdfRasterizer();
                rasterizer.Load(GetLocalPath(pdf.Path));
                rasterizer.Resolution = 300;
                rasterizer.ColorSpace = PdfRasterizerColorSpace.RGB;

                System.Drawing.Image[] images = rasterizer.ConvertToImages();
                var p = 1;
                var currentDir = _appSettings.StoragePath;
                CreateDirectory("/pdf_images/" + pdf.FileId);

                foreach (var file in Directory.GetFiles(currentDir + "/wwwroot/files/pdf_images/" + pdf.FileId)) {
                    File.Delete(file);
                }

                foreach (var image in images) {
                    var file = $"/pdf_images/{pdf.FileId}/SavePageCustomResolution_{p}.png";
                    var url = GetFullUrl(file);
                    image.Save(GetLocalPath(file));
                    p++;
                }
            } else {
                throw new Exception("PDF 파일만 등록 가능합니다.");
            }
        }

        public ArrayList GetPdfImages(CmFile pdf) {
            ArrayList files = new ArrayList();
            var currentDir = _appSettings.StoragePath;
            if (pdf != null)
                if (Directory.Exists(currentDir + "/wwwroot/files/pdf_images/" + pdf.FileId)) {
                    foreach (var file in Directory.GetFiles(currentDir + "/wwwroot/files/pdf_images/" + pdf.FileId)) {
                        files.Add(_FullUrl("/pdf_images/" + pdf.FileId + "/" + Path.GetFileName(file)));
                    }
                }
            return files;
        }

    }
}