using System.IO.Compression;
using System.Resources;
using System.Text;
using Flurl.Http;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;

namespace OpenAuth.App.ServiceApp.ShpGeo.Utils;

public class ShapeUtil
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="shpPath"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public static List<Dictionary<string, object>> getRows(string shpPath)
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// 支持
    /// </summary>
    /// <param name="shpPath"></param>
    /// <returns></returns>
    public static List<Dictionary<string, object>> ReadAllGeometry(string shpPath)
    {
        //  取得后缀，如果是zip,则解压
        var fileExtension = Path.GetExtension(shpPath);
        if (!fileExtension.Equals(".shp") && !fileExtension.Equals(".zip"))
        {
            throw new Exception("不支持的文件格式");
        }

        // 设置字符编码
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        var gbk = Encoding.GetEncoding("gbk");
        if (fileExtension == ".zip")
        {
            var extractPath = Path.GetDirectoryName(shpPath) + "\\temp";
            Directory.CreateDirectory(extractPath);

            using (var archive = ZipFile.OpenRead(shpPath))
            {
                // 列举ZIP文件中的条目
                foreach (var entry in archive.Entries)
                {
                    Console.WriteLine("zip 包含文件：");
                    var fileName = gbk.GetString(Encoding.Default.GetBytes(entry.FullName));
                    Console.WriteLine(fileName);
                }

                // 提取ZIP文件中的所有文件到指定目录

                foreach (var entry in archive.Entries)
                {
                    if (entry.Name != string.Empty)
                    {
                        // 确保完整路径存在  entry.FullName 是否可以编码
                        var fixedEntryName = entry.FullName.Replace("/", "");
                        var destinationPath = Path.GetFullPath(Path.Combine(extractPath, fixedEntryName));
                        Console.WriteLine("解压文件路径：" + destinationPath);
                        if (!destinationPath.StartsWith(Path.GetFullPath(extractPath) + Path.DirectorySeparatorChar))
                        {
                            throw new UnauthorizedAccessException("试图提取的文件超出了目标文件夹的路径边界。");
                        }

                        // 提取条目到目标路径
                        entry.ExtractToFile(destinationPath, overwrite: true);
                    }
                }
            }

            // 遍历解压目录，是否有shp后缀的文件
            if (!Directory.Exists(extractPath))
            {
                throw new Exception("文件解压失败");
            }

            // 查找
            var dirInfo = new DirectoryInfo(extractPath);
            // zip 压缩包中只有一个shp文件
            shpPath = dirInfo.GetFiles("*.shp", SearchOption.AllDirectories)[0].FullName;
        }

        var data = ParseShape(shpPath, null);
        var tifPath = data.First()["Image"].ToString();
        if (CheckForGarbledText(tifPath))
        {
            // 乱码，需要解码
            data = ParseShape(shpPath, gbk);
        }

        return data;
    }

    private static List<Dictionary<string, object>> ParseShape(string shpPath, Encoding code)
    {
        using var dataReader = code == null
            ? new ShapefileDataReader(shpPath, GeometryFactory.Default)
            : new ShapefileDataReader(shpPath, GeometryFactory.Default, code);
        Console.WriteLine("记录数" + dataReader.RecordCount);
        List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
        while (dataReader.Read())
        {
            Dictionary<string, object> row = new Dictionary<string, object>();
            // 读取列
            for (int i = 0, j = 0; i < dataReader.FieldCount; i++)
            {
                var colName = dataReader.GetName(i);
                var value = dataReader.GetValue(i);
                row.Add(colName, value);
            }

            rows.Add(row);
        }

        return rows;
        // return NetTopologySuite.IO.Esri.Shapefile.ReadAllGeometries(shpPath);
    }

    private static bool CheckForGarbledText(string content)
    {
        try
        {
            // 检查是否有不可打印的字符
            foreach (char c in content)
            {
                if (char.IsControl(c) && !char.IsWhiteSpace(c))
                {
                    return true; // 发现不可打印的控制字符
                }
            }

            // 检查是否有不常见的字符
            foreach (char c in content)
            {
                if (c > 0x7F && !char.IsLetterOrDigit(c) && !char.IsPunctuation(c) && !char.IsSymbol(c) &&
                    !char.IsWhiteSpace(c))
                {
                    return true; // 发现不常见的字符
                }
            }

            return false; // 没有发现乱码
        }
        catch (DecoderFallbackException)
        {
            return true; // 解码失败，存在乱码
        }
        catch (Exception ex)
        {
            return true; // 其他异常，可能表示存在乱码
        }
    }
}