using ryCommon;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ryCommon
{
    /// <summary>
    /// 
    /// </summary>
    public class ApkOp
    {
        /// <summary>
        /// 获取和设置aapt.exe的完整路径
        /// </summary>
        public string AAPT_Path { get; set; } = Application.StartupPath + "\\SysDb\\aapt.exe";
        /// <summary>
        /// 获取和设置缓存文件夹
        /// </summary>
        public string Cache_Folder { get; set; } = Application.StartupPath + "\\UserDb\\tmp";
        /// <summary>
        /// 是否开启深度分析,深度分析需要解压apk进行分析，会更耗时。
        /// </summary>
        public bool DeepAnaly_On { get; set; } = true;
        /// <summary>
        /// 读取adb内容
        /// </summary>
        /// <param name="apk_file"></param>
        /// <returns></returns>
        public ApkInfo Read_Apk(string apk_file)
        {
            ApkInfo apkinfo = new ApkInfo();
            try
            {
                if (!System.IO.File.Exists(apk_file) || System.IO.Path.GetExtension(apk_file).ToLower() != ".apk")
                {
                    try
                    {
                        apkinfo.FileName = System.IO.Path.GetFileName(apk_file);
                    }
                    catch (Exception ex)
                    {
                        apkinfo.ErrorMsg = "文件名格式错误=>" + ex.Message;
                    }
                    apkinfo.FilePath = apk_file;
                    return apkinfo;
                }
                String cmd = AAPT_Path;
                Process p = new Process
                {
                    StartInfo = new System.Diagnostics.ProcessStartInfo
                    {
                        FileName = cmd,//设定程序名
                        Arguments = "dump badging \"" + apk_file + "\"",
                        UseShellExecute = false, //关闭shell的使用
                        RedirectStandardInput = true, //重定向标准输入
                        RedirectStandardOutput = true, //重定向标准输出
                        RedirectStandardError = false, //重定向错误输出       
                        WorkingDirectory =System.IO.Path.GetDirectoryName(AAPT_Path),
                        StandardOutputEncoding = Encoding.UTF8,
                        CreateNoWindow = true//设置不显示窗口
                    }
                };
                p.Start();
                //byte[] buffer2 = Encoding.Default.GetBytes(p.StandardOutput.ReadToEnd());
                string result = p.StandardOutput.ReadToEnd();
                apkinfo.AppName = GetRegex(result, @"application:\slabel='(?<label>(.*))'\sicon='(?<icon>(.*))'", "label");
                //if (apkinfo.AppName == "") { result = p.StandardOutput.ReadToEnd(); apkinfo.AppName = GetRegex(result, @"application:\slabel='(?<label>(.*))'\sicon='(?<icon>(.*))'", "label"); }
                apkinfo.FileName = System.IO.Path.GetFileName(apk_file);
                apkinfo.FilePath = apk_file;
                apkinfo.PackageName = GetRegex(result, @"package:\sname='(?<name>(.*))'\sversionCode", "name");
                apkinfo.VersionCode = GetRegex(result, @"versionCode='(?<name>(.*))' ", "name").ToInt();
                apkinfo.VersionName = GetRegex(result, @"versionName='(?<name>(.*))'\s", "name");
                //sdk_ver:=RegExpr(dosStr,'sdkVersion:''(?<name>(.*))''\s','name');
                apkinfo.MinSDK = GetRegex(result, @"sdkVersion:'(?<name>(.*))'\s", "name").ToInt();
                var Permission = GetRegexList(result, @"uses-permission:'(?<name>(.*))'\s", "name");
                var text = "";
                for (int i = 0; i < Permission.Count; i++)
                {
                    if (Permission[i].Length == 0) { continue; }
                    if (text.Length > 0) { text += "\r\n"; }
                    text += Permission[i];
                }
                apkinfo.Permission = text;
                int index = apkinfo.VersionName.IndexOf("'");
                if (index > 0)
                {
                    apkinfo.VersionName = apkinfo.VersionName.Substring(0, index);
                }
                try
                {
                    FileInfo fi = new FileInfo(apk_file);
                    apkinfo.CreationTime = fi.CreationTime;
                    apkinfo.LastWriteTime = fi.LastWriteTime;
                }
                catch { }
                if (DeepAnaly_On)
                {
                    #region 分析apk图标
                    string apk_icon = GetRegex(result, @"application:\slabel='(?<label>(.*))'\sicon='(?<icon>(.*))'", "icon");
                    var list_icon = GetRegexList(result, @"application-icon-(.*)'(?<name>(.*))'", "name");
                    for (int i = list_icon.Count - 1; i >= 0; i--)
                    {
                        if (list_icon[i].EndsWith(".xml")) { list_icon.RemoveAt(i); }
                    }
                    if (list_icon.Count > 0) { apk_icon = list_icon[list_icon.Count - 1]; }
                    string apkicon_savepath = Cache_Folder + "\\apkicon_" + DateTime.Now.ToInt64() +".png";
                    try
                    {
                        #region 解压文件图标
                        if (System.IO.File.Exists(apkicon_savepath)) { System.IO.File.Delete(apkicon_savepath); }
                        try
                        {
                            var zips= ZipFile.OpenRead(apk_file);
                            for (int i = 0; i < zips.Entries.Count; i++)
                            {
                                var zip = zips.Entries[i];
                                if(zip.FullName.Replace("/", "\\").ToLower() == apk_icon.Replace("/", "\\").ToLower())
                                {
                                    string fileName = Path.GetFileName(zip.FullName);
                                     {
                                        #region 写入文件
                                        if (!System.IO.Directory.Exists(Cache_Folder))
                                        {
                                            System.IO.Directory.CreateDirectory(Cache_Folder);
                                        }
                                        //var tmp_icon = Cache_Folder.TrimEnd('\\') + "\\" + System.IO.Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToInt64() + System.IO.Path.GetExtension(fileName);
                                        zip.ExtractToFile(apkicon_savepath, true);//解压文件，如果已存在就覆盖
                                        //string errorMsg = "";
                                        //RyFiles.MoveFile(tmp_icon, apkicon_savepath, false, false, false, ref errorMsg);
                                        //fileItem.LastWriteTime = zipEntry.DateTime;
                                        #endregion
                                    }
                                }
                            }
                            zips.Dispose();
                        }
                        catch (Exception ex)
                        {
                            apkinfo.ErrorMsg = "解压报错=>" + ex.Message;
                        }
                        #endregion
                    }
                    catch
                    { }
                    if (System.IO.File.Exists(apkicon_savepath))
                    {
                        apkinfo.AppIcon = RyImage.LoadPic(apkicon_savepath);
                    }
                    //if (apkinfo.AppIcon == null) { apkinfo.AppIcon = null; }
                    #endregion
                }
                p.WaitForExit(8000);
                p.Close();
            }
            catch (Exception ex)
            {
                apkinfo.ErrorMsg = "读取APK信息报错=>" + ex.Message;
            }
            return apkinfo;
        }
        private string GetRegex(string text, string regex, string group)
        {
            RegexOptions option = RegexOptions.IgnoreCase | RegexOptions.Multiline;
            Regex reg = new Regex(regex, option);
            //返回一个结果
            Match result = reg.Match(text);
            return result.Groups[group].Value;
        }
        private List<string> GetRegexList(string text, string regex, string group)
        {
            RegexOptions option = RegexOptions.IgnoreCase | RegexOptions.Multiline;
            Regex reg = new Regex(regex, option);
            //返回一个结果集
            var result = reg.Matches(text);
            List<string> list = new List<string>();
            foreach (Match m in result)
            {
                list.Add(m.Groups[group].Value);
            }
            return list;
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class ApkInfo
    {
        /// <summary>
        /// app名称
        /// </summary>
        public string AppName { get; set; } = "";
        /// <summary>
        /// 包名
        /// </summary>
        public string PackageName { get; set; } = "";
        /// <summary>
        /// 版本号
        /// </summary>
        public int VersionCode { get; set; } = 0;
        /// <summary>
        /// 版本字符串
        /// </summary>
        public string VersionName { get; set; } = "";
        /// <summary>
        /// 权限
        /// </summary>
        public string Permission { get; set; } = "";
        /// <summary>
        /// 最小SDK
        /// </summary>
        public int MinSDK { get; set; } = 0;
        /// <summary>
        /// 应用图标,需开启DeepAnaly_On开关，否则无法获取
        /// </summary>
        public Image AppIcon { get; set; } = null;
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; } = "";
        /// <summary>
        /// 文件路径
        /// </summary>
        public string FilePath { get; set; } = "";
        /// <summary>
        /// 文件创建时间
        /// </summary>
        public DateTime CreationTime { get; set; } = new DateTime(1970, 1, 1);
        /// <summary>
        /// 文件修改时间
        /// </summary>
        public DateTime LastWriteTime { get; set; } = new DateTime(1970, 1, 1);
        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMsg { get; internal set; } = "";
    }
}
