using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;

namespace Mammonth.Common {

    /// <summary>
    /// 自定义HTML编辑器助手类
    /// <para>专门处理 百度ueditor HTML编辑器上传文件、图片的问题(避免出现垃圾图片)</para>
    /// </summary>
    /// <remarks>
    /// 创建人 zhao 2013-11-5
    /// </remarks>
    public class HtmlEditorHelper {

        /// <summary>
        /// 外部指定的网站网址
        /// </summary>
        public static string webUrl;

        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        public static string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

        /// <summary>
        /// 发送post请求
        /// </summary>
        /// <param name="url">请求的url</param>
        /// <param name="postString">发送到数据 例如:"name=xhan&password=1231"</param>
        /// <param name="encoding">发送和接受数据使用的编码</param>
        /// <returns>服务器响应字符串</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static string SendPostRequest(string postString) {
            if (postString == "") return "";

            string url = webUrl + "Handler1.ashx";
            Encoding encoding = Encoding.Default;
            byte[] postData = encoding.GetBytes(postString + "&name=xhan&password=1231");

            WebClient client = new WebClient();
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            client.Headers.Add("ContentLength", postData.Length.ToString());

            //MessageBox.Show(url);
            //MessageBox.Show("要删除的图片:"+postString);

            byte[] responseData = client.UploadData(url, "POST", postData);
            return encoding.GetString(responseData);
        }

        /// <summary>
        /// 上传图片,可以同时上传多张图片
        /// </summary>
        /// <param name="filepathList">本地物理路径</param>
        /// <param name="savePath">服务端保存路径;如hotel\34\2012060134223.jpg</param>
        /// <returns></returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static string UpFilesToServer(string folder, string id, IList<string> filepathList, IList<string> saveFileName) {
            if (filepathList.Count != saveFileName.Count) return "err";

            //string url = @"/Uploader.ashx?Overwrite=true&PATH=Logs\" + DateTime.Now.ToString("yyyy-MM-dd");
            string url = webUrl + "Handler1.ashx?action=upfiles&Overwrite=true&folder={0}&id={1}&filename={2}";

            for (int i = 0; i < filepathList.Count; i++) {
                System.Net.WebClient myWebClient = new System.Net.WebClient();
                myWebClient.UploadFile(string.Format(url, folder, id, saveFileName[i]), "POST", filepathList[i]);
            }
            return "ok";
        }

        /// <summary>
        /// 从HTML文本中获取所有图片路径
        /// 相对路径或者网络图片http://
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static IList<string> getImageSrcArray(string source) {
            IList<string> srcArr = new List<string>();

            string strRegExPattern = @"<img[^>]+(src)\s*=\s*""?([^ "">]+)""?(?:[^>]+(width|height)\s*=\s*""?([^ "">]+)""?\s+(height|width)\s*=\s*""?([^ "">]+)""?)?(?:[^>]+(alt)\s*=\s*""?([^"">]+)""?)?";

            Regex re = new Regex(strRegExPattern, RegexOptions.IgnoreCase);
            Match m = re.Match(source);

            while (m.Success) {
                srcArr.Add(m.Groups[2].Value);
                m = m.NextMatch();
            }
            return srcArr;
        }

        /// <summary>
        /// 对比A\B两个图片列表，找出存在于B但不存在于A中的图片,(就是找出B中的垃圾图片)
        /// </summary>
        /// <param name="newsrcList">A图片列表 新图片</param>
        /// <param name="oldSrcList">B图片列表 老图片</param>
        /// <returns></returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static IList<string> getDelImagesSrcArray(IList<string> newsrcList, string oldSrcList) {
            IList<string> delsrclist = new List<string>();

            //对比，要删除远程服务器上的图片
            if (oldSrcList != "") {
                if (oldSrcList.IndexOf("|") == -1)
                    oldSrcList += "|";

                string[] oldsrcs = oldSrcList.Split(new char[] { '|' });

                if (newsrcList.Count > 0) {
                    for (int i = 0; i < oldsrcs.Length; i++)//遍历旧的
                    {
                        bool ishas = false;
                        for (int j = 0; j < newsrcList.Count; j++)//遍历新的
                        {
                            if (oldsrcs[i] == newsrcList[j])//旧的在新列表存在
                            {
                                ishas = true;
                                break;
                            }
                        }
                        if (!ishas) {
                            delsrclist.Add(oldsrcs[i]);
                        }
                    }
                } else {
                    for (int i = 0; i < oldsrcs.Length; i++)//遍历旧的
                    {

                        if (oldsrcs[i] != "")
                            delsrclist.Add(oldsrcs[i]);
                    }
                }
            }

            return delsrclist;
        }

        /// <summary>
        /// 对比A\B两个图片列表，找出存在于B但不存在于A中的图片,(就是找出B中的垃圾图片)
        /// </summary>
        /// <param name="newsrcList">A图片列表 新图片，相对路径</param>
        /// <param name="oldSrcList">B图片列表 老图片，相对路径</param>
        /// <returns>IList</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static IList<string> getDelImagesSrcArray(IList<string> newsrcList, IList<string> oldSrcList) {
            IList<string> delsrclist = new List<string>();

            //对比，要删除远程服务器上的图片
            //if (oldSrcList != "")
            //{
            //    if (oldSrcList.IndexOf("|") == -1)
            //        oldSrcList += "|";

            //    string[] oldsrcs = oldSrcList.Split(new char[] { '|' });

            if (oldSrcList != null) {

                if (newsrcList.Count > 0) {
                    for (int i = 0; i < oldSrcList.Count; i++)//遍历旧的
                    {
                        bool ishas = false;
                        for (int j = 0; j < newsrcList.Count; j++)//遍历新的
                        {
                            if (oldSrcList[i] == newsrcList[j])//旧的在新列表存在
                            {
                                ishas = true;
                                break;
                            }
                        }
                        if (!ishas) {
                            delsrclist.Add(oldSrcList[i]);
                        }
                    }
                } else {
                    for (int i = 0; i < oldSrcList.Count; i++)//遍历旧的
                    {

                        if (oldSrcList[i] != "")
                            delsrclist.Add(oldSrcList[i]);
                    }
                }
                //}
            }
            return delsrclist;
        }

        /// <summary>
        /// 删除远程图片
        /// </summary>
        /// <param name="files">要删除的物理路径集合</param>
        /// <returns>int</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static int DelServerFiles(IList<string> files) {
            if (files.Count == 0) return 0;
            int cnt = 0;
            for (int i = 0; i < files.Count; i++) {
                if (files[i] != "" && System.IO.File.Exists(files[i])) {
                    try {
                        System.IO.File.Delete(files[i]);//即可，比如File.Delete(MapPath("../aaa/bb.jpg"));
                        cnt++;
                    } catch {//(System.Exception ex)
                        // context.Response.Write(imgpaths + "<br/>" + ex.Message);
                    }
                }
            }
            return cnt;
        }

        /// <summary>
        /// 移动远程图片
        /// </summary>
        /// <param name="files">要移动的物理路径集合</param>
        /// <param name="folder">目标物理路径</param>
        /// <param name="IsDelete">是否删除临时文件,默认true删除</param>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>  
        ///     <![CDATA[
        ///      int moveresult = HtmlImagesHelper.RemoveServerFiles(ChgServerMapPath(NewImgList), HttpContext.Current.Server.MapPath("/oa/data/Cruise/news/" + model.Id.ToString())); 
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <returns>int</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static int RemoveServerFiles(IList<string> files, string folder, bool IsDelete = true) {
            if (files.Count == 0) return 0;
            //--检查目录是否存在
            if (!System.IO.Directory.Exists(folder)) {
                System.IO.Directory.CreateDirectory(folder);
            }
            if (folder.EndsWith("\\"))
                folder = folder.Remove(folder.Length - 1);
            int count = 0;
            for (int i = 0; i < files.Count; i++) {
                string path = files[i];
                string newPath = folder + "\\" + System.IO.Path.GetFileName(path);
                //源文件必须存在，目标文件不存在，（已经存在就替换）
                if (path != "" && path != newPath && System.IO.File.Exists(path)) { //&& !System.IO.File.Exists(newPath)//目标文件不存在
                    try {
                        if (IsDelete) {
                            System.IO.File.Move(path, newPath);////删除来源图片 Move（）方法会自动删除源文件
                        } else {
                            System.IO.File.Copy(path, newPath);
                        }  
                        count++;
                    } catch {//(System.Exception ex) 

                    }
                }
            }
            return count;
        }


        /// <summary>
        /// 更改HTML文本中的图片路径为指定路径
        /// <para>把临时目录改成业务实际需要存放的目录</para>
        /// </summary>
        /// <param name="content">HTML文本</param>      
        /// <param name="folder">实际要存放的目标路径（相对路径）</param>
        /// <param name="files">输出文本中的图片路径集合（相对路径）</param>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>  
        ///     <![CDATA[
        ///      theModel.Content = HtmlImagesHelper.ChangeImagesPath(model.Content, "/oa/data/Cruise/news/" + model.Id.ToString(), out NewImgList);		//详细内容        
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <returns>string</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static string ChangeImagesPath(string content, string targetFolder, out IList<string> files) {

            files = getImageSrcArray(content);//路径集合
            if (files.Count == 0)
                return content;
            //
            if (targetFolder == "")
                return content;
            //

            if (targetFolder.EndsWith("/")) {
                targetFolder = targetFolder.Remove(targetFolder.Length - 1);
            }

            //////////////////////
            IList<string> realpaths = new List<string>();
            for (int i = 0; i < files.Count; i++) {
                string path = files[i];
                //固定的临时上传目录 "/uploads/ueditor/upload" 和  "/uploads/ueditor/upload1"
                //如果能找到这个特征目录，说明图片是新上传的，还在临时文件夹中
                if (path.IndexOf("/uploads/ueditor/upload") > -1) {
                    //如 /oa/uploads/ueditor/upload/2013-09-30/210.jpg
                    string tmppath = System.IO.Path.GetDirectoryName(path); //如 \\oa\\uploads\\ueditor\\upload\\2013-09-30
                    //string tmpfile = System.IO.Path.GetFileName(path);      //如 210.jpg                    
                    tmppath = tmppath.Replace("\\", "/");
                    if (realpaths.IndexOf(tmppath) == -1) {
                        realpaths.Add(tmppath);// /oa/uploads/ueditor/upload/2013-09-30/210.jpg
                    }
                }
            }
            //需要替换的路径集合
            if (realpaths.Count == 0) {
                return content;
            }

            //--替换
            for (int j = 0; j < realpaths.Count; j++) {
                content = content.Replace(realpaths[j], targetFolder);
            }
            //
            return content;
        }

        /// <summary>
        /// 直接在数据库中更改指定表格指定字段内容的图片路径
        /// <para>把临时目录改成业务实际需要存放的目录</para>
        /// </summary>
        /// <param name="files">图片相对（虚拟）路径集合</param>
        /// <param name="folder">目标文件夹</param>
        /// <param name="tablename">表格名称</param>
        /// <param name="fields">列集合,多个列以逗号","隔开</param>
        /// <param name="condition">SQL查询更新条件</param>
        /// <example> 这是一个例子显示如何调用此方法
        ///     <code>  
        ///     <![CDATA[
        ///      HtmlImagesHelper.UpdateFilesPath(NewImgList, "/oa/data/Cruise/news/" + model.Id.ToString(), "T_Cruise_News", "Content", "Id=" + model.Id.ToString());
        ///     ]]>  
        ///     </code>
        /// </example>
        /// <returns>int</returns>
        /// <remarks>
        /// 创建人 zhao 2013-11-5
        /// </remarks>
        public static int UpdateFilesPath(IList<string> files, string folder, string tablename, string fields, string condition) {

            if (files.Count == 0)
                return 0;
            if (folder == "" || tablename == "" || fields == "" || condition == "")
                return 0;
            if (folder.EndsWith("/")) {
                folder = folder.Remove(folder.Length - 1);
            }

            /////////////////////////
            IList<string> fieldList = new List<string>();
            if (fields.IndexOf(",") == -1) {
                fieldList.Add(fields);
            } else {
                string[] tempfds = fields.Split(new Char[] { ',' });
                for (int i = 0; i < tempfds.Length; i++) {
                    fieldList.Add(tempfds[i]);
                }
            }
            //////////////////////
            IList<string> realpaths = new List<string>();
            for (int i = 0; i < files.Count; i++) {
                string path = files[i];
                //还在临时文件夹中
                if (path.IndexOf("/uploads/ueditor/upload") > -1) {
                    //如 /uploads/ueditor/upload/2013-09-30/210.jpg
                    string tmppath = System.IO.Path.GetDirectoryName(path); //如 \\uploads\\ueditor\\upload\\2013-09-30
                    //string tmpfile = System.IO.Path.GetFileName(path);      //如 210.jpg                    
                    tmppath = tmppath.Replace("\\", "/");
                    if (realpaths.IndexOf(tmppath) == -1) {
                        realpaths.Add(tmppath);// /uploads/ueditor/upload/2013-09-30/210.jpg
                    }
                }
            }
            if (realpaths.Count == 0) {
                return 0;
            }
            ////////////////////////
            string selectSQL = "select ", updateSQL = "update [" + tablename + "] Set ";
            for (int i = 0; i < fieldList.Count; i++) {
                if (i > 0) {
                    selectSQL += ",";
                    updateSQL += ",";
                }
                selectSQL += fieldList[i];
                updateSQL += string.Format("{0} = @{1}", fieldList[i], fieldList[i]);
            }
            selectSQL += string.Format(" from {0} where {1}", tablename, condition);
            updateSQL += string.Format(" where {0}", condition);

            ////////////////////////
            using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connectionString)) {
                conn.Open();

                System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
                cmd.Connection = conn;
                //--获取
                cmd.CommandText = selectSQL;
                System.Data.SqlClient.SqlDataReader reader = cmd.ExecuteReader();
                IList<string> oldtexts = new List<string>();
                if (reader.Read()) {
                    for (int i = 0; i < fieldList.Count; i++) {
                        oldtexts.Add((reader.GetValue(i) != DBNull.Value) ? reader.GetString(i) : "");
                    }
                }
                reader.Close();
                if (oldtexts.Count > 0) {
                    //--替换
                    for (int i = 0; i < fieldList.Count; i++) {
                        //
                        for (int j = 0; j < realpaths.Count; j++) {
                            string oldstr = realpaths[j];
                            oldtexts[i] = oldtexts[i].Replace(oldstr, folder);
                        }
                        //
                        cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@" + fieldList[i], oldtexts[i]));
                    }
                    cmd.CommandText = updateSQL;
                    cmd.ExecuteNonQuery();
                }
                //--释放连接资源
                cmd.Dispose();
                conn.Close();
            }
            return 0;
        }
        /// <summary>
        /// 转换成服务器物理路径
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        /// <remarks>
        /// 创建 zhao 2013-11-5
        /// </remarks>
        public static IList<string> ChgServerMapPath(System.Web.HttpContext context, IList<string> list) {
            IList<string> SrcList = new List<string>();
            if (list.Count > 0) {
                //遍历旧的
                for (int i = 0; i < list.Count; i++) {
                    if (list[i].Substring(0, 7).ToLower() == "http://")
                        continue;
                    SrcList.Add(context.Server.MapPath(list[i]));
                }
            }
            return SrcList;
        }
        /// <summary>
        /// 对HTML编辑器中的图片进行特殊处理
        /// <para>如删除无效垃圾图片</para>
        /// <para>  将图片保存到更合理的目录</para>
        /// </summary>
        /// <param name="context">System.Web.HttpContext</param>
        /// <param name="oldImgList">老图片列表</param>
        /// <param name="newImgList">新图片列表</param>
        /// <param name="targetfolder">图片要保持的相对路径，如：oa\data\00001\hotel\240,不能以\开头结尾</param>
        /// <param name="tableName">保存内容的目标表格名称,如："T_Hotel"</param>
        /// <param name="fieldName">保存内容的目标字段名称,多个列以逗号","隔开,如："Content,Note"</param>
        /// <param name="contions">更新目标字段的条件,如:"ID=240"</param>
        /// <param name="IsDelete">是否删除临时文件,默认true删除</param>
        /// <returns>返回受影响的图片数量</returns>
        /// <remarks>
        /// 创建：zhaoshunlu 2014-06-24
        /// </remarks>
        public static int AccessImages(System.Web.HttpContext context, IList<string> oldImgList, IList<string> newImgList, string targetfolder, string tableName, string fieldName, string contions,bool IsDelete=true) {

            if (targetfolder.StartsWith("\\")) targetfolder = targetfolder.Remove(0, 1);
            if (targetfolder.EndsWith("\\")) targetfolder = targetfolder.Remove(targetfolder.Length-1, 1);

            string rootfolder = context.Server.MapPath("/");//网站物理根目录,后面已经有\，如c:\wwwroot\web\
            int delresult = 0;   //删除图片数量
            int moveresult = 0;  //移动图片数量
            //
            //--1、算出要删除的图片列表
            IList<string> DelSrcList = getDelImagesSrcArray(newImgList, oldImgList); //老图片    
            //--2、如果存在无效图片，就删除远程无效图片  
            if (DelSrcList.Count > 0)
                delresult = DelServerFiles(ChgServerMapPath(context, DelSrcList));

            //--3、移动远程图片（把新加入的图片移动到指定文件夹）
            moveresult = RemoveServerFiles(ChgServerMapPath(context, newImgList), rootfolder + targetfolder,IsDelete);
            //--4、更新数据库中新加入图片的路径(把临时文件夹改为移动后ID文件夹)
            if (moveresult > 0)
                moveresult = UpdateFilesPath(newImgList, "/" + targetfolder.Replace("\\", "/"), tableName, fieldName, contions);

            //
            return delresult + moveresult;
        }

    }
}
