using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using System.Xml.Serialization;
using LitJson;
using RFrameGenerate.BLL;
using RFrameGenerate.Common;
using RFrameGenerate.Model;
using RFramework.SQLServer;
using Wechat.Model;

namespace jiouosdp.Areas.Materials.Controllers
{
    public class MaterialsMgeController : Controller
    {
        //
        // GET: /Materials/MaterialsMge/

        [PF(PCode.WeiXinManage.MaterialsMge)]
        public ActionResult Index()
        {
            return View();
        }

        #region JsonResult GetList //Material/Sort

        /// <summary>
        /// get material list
        /// </summary>
        /// <param name="gridModel"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public JsonResult GetMaterialsList(GridModel gridModel, string type)
        {
            var mlist = MaterialsManage.GetMaterialList(gridModel, type);
            gridModel.datarows = (mlist.Select(c => new
            {
                id = c.MaterialGuid,
                cell = new object[]
                {
                    c.Name,
                    c.Content,
                    ""
                }
            }).ToArray());
            return Json(gridModel.PackagePageModel());
        }

        /// <summary>
        /// get sort list
        /// </summary>
        /// <param name="materialGuid"></param>
        /// <returns></returns>
        public JsonResult GetSortList(Guid materialGuid)
        {
            var list = MaterialTxtManage.GetSortList(materialGuid);
            return Json(new { Result = "OK", Data = list });
        }

        /// <summary>
        /// get upload list
        /// </summary>
        /// <param name="length"></param>
        /// <param name="txtname"></param>
        /// <param name="txtdescribe"></param>
        /// <param name="txtauthor"></param>
        /// <param name="txturl"></param>
        /// <param name="materialTxtlGuid"></param>
        /// <param name="txtcover"></param>
        /// <param name="materialsGuid"></param>
        /// <param name="isUpdate"></param>
        /// <param name="addIndex"></param>
        /// <returns></returns>
        private static List<T_BAS_MaterialTxt> GetUploadList(int length, string txtname, string txtdescribe,
            string txtauthor, string txturl,
            string materialTxtlGuid, string txtcover, ref string materialsGuid, ref bool isUpdate, ref string addIndex)
        {
            var list = new List<T_BAS_MaterialTxt>();

            for (int i = 0; i < length; i++)
            {
                list.Add(new T_BAS_MaterialTxt());
            }
            int j = 0;
            for (int i = length - 1; i > -1; i--)
            {
                list[i].Name = txtname.Split(',')[j];
                list[i].TXTAuthor = txtauthor.Split(',')[j];
                list[i].TXTDescribe = txtdescribe.Split(',')[j];
                list[i].TXTUrl = txturl.Split(',')[j];
                if (txtcover.Split(',')[j].Length > 1)
                {
                    list[i].TXTCover = txtcover.Split(',')[j];
                }
                if (materialTxtlGuid.Split(',')[j].Length == 0)
                {
                    addIndex += i + ",";
                    list[i].MaterialTxtlGuid = Guid.NewGuid();
                    isUpdate = true;
                }
                else
                {
                    list[i].MaterialTxtlGuid = Guid.Parse(materialTxtlGuid.Split(',')[j]);
                }
                if (string.IsNullOrEmpty(materialsGuid))
                {
                    materialsGuid = Guid.Empty.ToString();
                }
                j++;
            }
            return list;
        }

        #endregion

        #region Result Upload()  //upload txt/video/voice/image

        /// <summary>
        /// Upload all
        /// </summary>
        [HttpPost]
        public Result Upload()
        {
            string relativePath = string.Empty;
            Result result = new Result(false);
            Exception e = new Exception("上传的文件有误，请检查您的文件是否正确。");
            var materialGuid = string.IsNullOrEmpty(Request.Form["MaterialGuid"])
                ? Guid.Empty
                : Guid.Parse(Request.Form["MaterialGuid"]);
            var name = "";
            var materialType = Request.Form["MaterialType"];
            foreach (string upload in Request.Files)
            {
                var file = Request.Files[upload];
                if (file == null) continue;
                var extension = Path.GetExtension(file.FileName);
                if (extension == null) continue;
                var fileNameExt = extension.ToLower();
                var basePath = "";
                var material = "";
                switch (materialType)
                {
                    case "图片":
                        material = "image";
                        name = Request.Form["Name_image"];
                        if (fileNameExt != ".jpg" && fileNameExt != ".png")
                        {
                            e = new Exception("不合适的文件,只能支持jpg|png的文件");
                            return new Result(false, e.Message);
                        }
                        if (file.ContentLength > 512000)
                        {
                            e = new Exception("上传的图片请少于500KB");
                            return new Result(false, e.Message);
                        }
                        basePath = AppDomain.CurrentDomain.BaseDirectory + "upload/material/" + material + "/";
                        break;
                    case "音频":
                        material = "voice";
                        name = Request.Form["Name_voice"];
                        if (fileNameExt != ".mp3" && fileNameExt != ".amr")
                        {
                            e = new Exception("不合适的文件,只能支持mp3|amr的文件");
                            return new Result(false, e.Message);
                        }
                        if (file.ContentLength > 262144)
                        {
                            e = new Exception("上传的音频请少于256KB");
                            return new Result(false, e.Message);
                        }
                        basePath = AppDomain.CurrentDomain.BaseDirectory + "upload/material/" + material + "/";
                        break;
                    case "视频":
                        material = "video";
                        name = Request.Form["Name_video"];
                        if (fileNameExt != ".mp4")
                        {
                            e = new Exception("不合适的文件,只能支持mp4的文件");
                            return new Result(false, e.Message);
                        }
                        if (file.ContentLength > 10485760)
                        {
                            e = new Exception("上传的视频请少于10MB");
                            return new Result(false, e.Message);
                        }
                        basePath = AppDomain.CurrentDomain.BaseDirectory + "upload/material/" + material + "/";
                        break;
                }
                if (!file.HasFile()) continue;

                var dateTimeNow = DateTime.Now;
                if (Request.UrlReferrer == null) continue;

                Guid parGuid = Guid.NewGuid();
                var fileName = parGuid + fileNameExt;
                relativePath = basePath + "/" + fileName;
                file.SaveInFileSystem(basePath, fileName);
                var content = "/upload/material/" + material + "/" + fileName;
                var entity = new T_BAS_Materials
                {
                    MaterialGuid = materialGuid,
                    Name = name,
                    Content = content,
                    MaterialType = materialType
                };
                result = MaterialsManage.AddAndUpdateMaterials(entity);

            }

            return new Result(result.State, e.Message);
        }

        /// <summary>
        /// upload txt info
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult UploadTxt()
        {
            string relativePath = string.Empty;
            var content = "";
            var materialType = Request.Form["MaterialType"];
            try
            {
                foreach (string upload in Request.Files)
                {
                    var file = Request.Files[upload];
                    if (file == null) continue;
                    var extension = Path.GetExtension(file.FileName);
                    if (extension == null) continue;
                    var fileNameExt = extension.ToLower();
                    if (fileNameExt != ".jpg" && fileNameExt != ".png")
                    {
                        throw new Exception("不合适的文件,只能支持jpg|png的文件");
                    }
                    if (file.ContentLength > 512000)
                    {
                        throw new Exception("上传的图片请少于500KB");
                    }
                    var dateTimeNow = DateTime.Now;
                    if (Request.UrlReferrer == null) continue;
                    Guid parGuid = Guid.NewGuid();
                    var fileName = parGuid + fileNameExt;
                    var basePath = AppDomain.CurrentDomain.BaseDirectory + "upload/material/txt/";
                    relativePath = basePath + "/" + fileName;
                    file.SaveInFileSystem(basePath, fileName);
                    content = "/upload/material/txt/" + fileName;
                }

                Hashtable successHash = new Hashtable();
                successHash["error"] = 0;
                successHash["url"] = content;
                Response.AddHeader("Content-Type", "text/html; charset=UTF-8");
                Response.Write(JsonMapper.ToJson(successHash));
                Response.End();
                
            }
            catch (Exception e)
            {
                Hashtable failueHash = new Hashtable();
                failueHash["error"] = 1;
                failueHash["message"] = e.Message;
                Response.AddHeader("Content-Type", "text/html; charset=UTF-8");
                Response.Write(JsonMapper.ToJson(failueHash));
                Response.End();
            }
            return Json(new { Result = "OK"}, content);
        }

        #endregion

        #region JsonResult //add/update/delete

        /// <summary>
        /// add and update materials
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public JsonResult AddAndUpdateMatreials(T_BAS_Materials entity)
        {
            var result = MaterialsManage.AddAndUpdateMaterials(entity);
            return result.State ? Json(new { Result = "OK" }) : Json(new { Result = "NO", Msg = result.Msg });
        }

        /// <summary>
        /// add or update material (all)
        /// </summary>
        /// <returns></returns>
        public JsonResult AddOrUpdateMaterial()
        {
            var result = Upload();
            return result.State == true ? Json(new { Result = "OK" }) : Json(new { Result = "NO", Msg = result.Msg });
        }

        /// <summary>
        /// delete materials(all)
        /// </summary>
        /// <param name="materialGuid"></param>
        /// <returns></returns>
        public JsonResult DeleteMaterials(Guid materialGuid)
        {
            return MaterialsManage.DeleteMaterials(materialGuid).State
                ? Json(new { Result = "OK" })
                : Json(new { Result = "NO" });
        }

        /// <summary>
        /// delete materials(txt)
        /// </summary>
        /// <param name="materialGuid"></param>
        /// <returns></returns>
        public JsonResult DeleteTxtMaterials(Guid materialGuid)
        {
            if (KeywordsManage.EqualByMaterialsGuid(materialGuid) > 0)
            {
                return Json(new { Result = "NO", Msg = "删除失败，素材正在使用!" });
            }

            using (var tran = new SqlRTransaction())
            {
                tran.BeginTransaction();
                MaterialTxtManage.DeleteTxtMaterials(materialGuid);
                MaterialsManage.DeleteMaterials(materialGuid);
                tran.Commit();
            }

            return Json(new { Result = "OK" });
        }

        /// <summary>
        /// add and update materialtxt
        /// function f :NormalOperating
        /// function s :UpdateByChangeOperating
        /// function t :MoreOpreating
        /// </summary>
        /// <param name="txtname"></param>
        /// <param name="txtdescribe"></param>
        /// <param name="txtauthor"></param>
        /// <param name="txturl"></param>
        /// <param name="materialTxtlGuid"></param>
        /// <param name="txtcover"></param>
        /// <param name="materialsGuid"></param>
        /// <returns></returns>
        public JsonResult AddAndUpdateTxtMaterials(string txtname, string txtdescribe, string txtauthor, string txturl,
            string materialTxtlGuid, string txtcover, string materialsGuid)
        {
            var length = txtname.Split(',').Length - 1;
            var mlist = new List<T_BAS_MaterialTxt>();
            var isMoreOpreating = 0;
            var isUpdate = false;
            var addIndex = "";
            var dataList = GetUploadList(length, txtname, txtdescribe, txtauthor, txturl, materialTxtlGuid, txtcover,
                ref materialsGuid, ref isUpdate, ref addIndex);

            if (!string.IsNullOrEmpty(materialsGuid))
            {
                mlist = MaterialTxtManage.GetMaterialsTxtList(Guid.Parse(materialsGuid));
            }
            isMoreOpreating = CheckIsMoreOpreating(mlist, dataList, isMoreOpreating);

            if (!string.IsNullOrEmpty(materialsGuid) && mlist.Count != length && isMoreOpreating != 0 && string.IsNullOrEmpty(addIndex))
            {
                UpdateByChangeOperating(length, txtname, txtdescribe, txtauthor, txturl, materialTxtlGuid, txtcover,
                    materialsGuid, mlist, dataList);
            }

            else if (isMoreOpreating == 0 || isMoreOpreating == mlist.Count)
            {
                NormalOperating(length, txtname, txtdescribe, txtauthor, txturl, materialTxtlGuid, txtcover,
                    materialsGuid, dataList, isUpdate, addIndex);
            }

            else
            {
                var addList = new List<T_BAS_MaterialTxt>();
                var deleteList = new List<T_BAS_MaterialTxt>();

                addIndex = addIndex.Substring(0, addIndex.Length - 1);

                foreach (var a in addIndex.Split(','))
                {
                    addList.Add(dataList[int.Parse(a)]);
                }

                for (int j = 0; j < mlist.Count; j++)
                {
                    var isContain = 0;
                    for (int i = 0; i < dataList.Count; i++)
                    {
                        if (mlist[j].MaterialTxtlGuid.ToString()
                            .Contains(dataList[i].MaterialTxtlGuid.ToString()))
                        {
                            isContain++;
                        }
                    }
                    if (isContain == 0)
                    {
                        deleteList.Add(mlist[j]);
                    }
                }

                using (var tran = new SqlRTransaction())
                {
                    tran.BeginTransaction();

                    for (int j = 0; j < deleteList.Count; j++)
                    {
                        MaterialTxtManage.DeleteTxtMaterialsByGuid(deleteList[j].MaterialTxtlGuid);
                    }

                    for (var k = 0; k < mlist.Count; k++)
                    {
                        mlist = MaterialTxtManage.GetMaterialsTxtList(Guid.Parse(materialsGuid));
                        var num = 0;
                        for (int i = 0; i < deleteList.Count; i++)
                        {
                            if (mlist[k].Sort > deleteList[i].Sort)
                            {
                                num++;
                            }
                        }
                        MaterialTxtManage.UpdateSorf(mlist[k].MaterialTxtlGuid,
                            mlist[k].Sort.Value - num);
                    }

                    var sort = 0;
                    for (int j = 0; j < addList.Count; j++)
                    {
                        addList[j].MaterialGuid = Guid.Parse(materialsGuid);
                        addList[j].Sort = mlist.Count + sort;
                        sort++;

                    }
                    MaterialTxtManage.AddSimpleTxt(addList);
                    for (var k = 0; k < length; k++)
                    {
                        MaterialTxtManage.UpdatAllTxt(dataList[k]);
                    }

                    tran.Commit();
                }

            }
            return Json(new { Result = "OK" });
        }



        #endregion

        #region private //AddAndUpdateTxtMaterials Function

        /// <summary>
        /// update by change operating is add and there is  new a txt or delete a txt ar update 
        /// new a txt or delete a txt at update this will lead to data list count is not eq to database length
        /// </summary>
        /// <param name="length"></param>
        /// <param name="txtname"></param>
        /// <param name="txtdescribe"></param>
        /// <param name="txtauthor"></param>
        /// <param name="txturl"></param>
        /// <param name="materialTxtlGuid"></param>
        /// <param name="txtcover"></param>
        /// <param name="materialsGuid"></param>
        /// <param name="materialsTxtList"></param>
        /// <param name="dataList"></param>
        private static void UpdateByChangeOperating(int length, string txtname, string txtdescribe, string txtauthor,
            string txturl, string materialTxtlGuid, string txtcover, string materialsGuid,
            List<T_BAS_MaterialTxt> materialsTxtList, List<T_BAS_MaterialTxt> dataList)
        {
            var contStr = "";
            var listMar = Guid.Empty;
            var marGuid = Guid.Empty;
            var index = 0;
            if (materialsTxtList.Count > dataList.Count)
            {
                var sortStr = new int[materialsTxtList.Count - dataList.Count];
                for (int j = 0; j < materialsTxtList.Count; j++)
                {
                    var isContain = 0;
                    for (int i = 0; i < dataList.Count; i++)
                    {
                        if (materialsTxtList[j].MaterialTxtlGuid.ToString()
                            .Contains(dataList[i].MaterialTxtlGuid.ToString()))
                        {
                            isContain++;

                        }
                    }
                    if (isContain == 0)
                    {
                        contStr += materialsTxtList[j].MaterialTxtlGuid + ",";
                        sortStr[index] = materialsTxtList[j].Sort.Value;
                        index++;
                    }
                }

                sortStr = GetExecArray(sortStr);

                if (!string.IsNullOrEmpty(contStr))
                {
                    using (var tran = new SqlRTransaction())
                    {
                        tran.BeginTransaction();
                        for (int j = 0; j < contStr.Split(',').Length; j++)
                        {
                            if (!string.IsNullOrEmpty(contStr.Split(',')[j]))
                            {
                                MaterialTxtManage.DeleteTxtMaterialsByGuid(Guid.Parse(contStr.Split(',')[j]));
                            }
                        }


                        for (var k = 0; k < materialsTxtList.Count; k++)
                        {
                            materialsTxtList = MaterialTxtManage.GetMaterialsTxtList(Guid.Parse(materialsGuid));
                            var num = 0;
                            for (int i = 0; i < sortStr.Length; i++)
                            {
                                if (materialsTxtList[k].Sort > sortStr[i])
                                {
                                    num++;
                                }
                            }
                            MaterialTxtManage.UpdateSorf(materialsTxtList[k].MaterialTxtlGuid,
                                materialsTxtList[k].Sort.Value - num);
                        }

                        for (var k = 0; k < length; k++)
                        {
                            MaterialTxtManage.UpdatAllTxt(dataList[k]);
                        }

                        tran.Commit();
                    }
                }
            }
            else
            {
                var addList = new List<T_BAS_MaterialTxt>();
                for (int j = 0; j < dataList.Count; j++)
                {
                    var isContain = 0;
                    for (int i = 0; i < materialsTxtList.Count; i++)
                    {
                        if (dataList[j].MaterialTxtlGuid.ToString()
                            .Contains(materialsTxtList[i].MaterialTxtlGuid.ToString()))
                        {
                            isContain++;

                        }
                    }
                    if (isContain == 0)
                    {
                        dataList[j].MaterialGuid = Guid.Parse(materialsGuid);
                        dataList[j].Sort = j;
                        addList.Add(dataList[j]);
                    }
                }

                using (var tran = new SqlRTransaction())
                {
                    tran.BeginTransaction();

                    MaterialTxtManage.AddSimpleTxt(addList);

                    for (var k = 0; k < length; k++)
                    {
                        MaterialTxtManage.UpdatAllTxt(dataList[k]);
                    }

                    tran.Commit();
                }
            }
        }



        /// <summary>
        /// get array order by exec
        /// </summary>
        /// <param name="sortStr"></param>
        private static int[] GetExecArray(int[] sortStr)
        {
            for (int i = 0; i < sortStr.Length; i++)
            {
                for (int j = i; j < sortStr.Length; j++)
                {
                    if (sortStr[i] > sortStr[j])
                    {
                        int temp = sortStr[i];
                        sortStr[i] = sortStr[j];
                        sortStr[j] = temp;
                    }
                }
            }
            return sortStr;
        }


        /// <summary>
        /// normal operating is add and there is no new a txt or delete a txt ar update 
        /// new a txt or delete a txt at update this will lead to data list count is not eq to database length
        /// </summary>
        /// <param name="length"></param>
        /// <param name="txtname"></param>
        /// <param name="txtdescribe"></param>
        /// <param name="txtauthor"></param>
        /// <param name="txturl"></param>
        /// <param name="materialTxtlGuid"></param>
        /// <param name="txtcover"></param>
        /// <param name="materialsGuid"></param>
        /// <param name="dataList"></param>
        /// <param name="isUpdate"></param>
        /// <param name="addIndex"></param>
        private static void NormalOperating(int length, string txtname, string txtdescribe, string txtauthor, string txturl, string materialTxtlGuid, string txtcover, string materialsGuid, List<T_BAS_MaterialTxt> dataList, bool isUpdate, string addIndex)
        {
            using (var tran = new SqlRTransaction())
            {
                tran.BeginTransaction();
                var mar = new T_BAS_Materials
                {
                    MaterialGuid = Guid.Parse(materialsGuid.ToString()),
                    Name = dataList[0].Name,
                    Content = dataList[0].TXTCover,
                    MaterialType = "图文"
                };
                MaterialsManage.AddAndUpdateTxtMaterials(mar);

                if (isUpdate)
                {
                    addIndex = addIndex.Substring(0, addIndex.Length - 1);

                    foreach (var a in addIndex.Split(','))
                    {
                        int num = Int32.Parse(a);
                        T_BAS_MaterialTxt m = dataList[num];
                        m.MaterialGuid = mar.MaterialGuid;
                        m.Sort = num;
                        MaterialTxtManage.AddOrUpdateTxt(dataList[num]);
                        dataList.RemoveAt(num);
                    }
                    for (int i = 0; i < dataList.Count; i++)
                    {
                        dataList[i].MaterialGuid = mar.MaterialGuid;
                    }
                    MaterialTxtManage.UpdateSimpleTxt(dataList);

                }
                else
                {
                    for (int i = 0; i < dataList.Count; i++)
                    {
                        dataList[i].MaterialGuid = mar.MaterialGuid;
                    }
                    MaterialTxtManage.UpdateSimpleTxt(dataList);
                }

                tran.Commit();
            }
        }

        /// <summary>
        /// check this opreating is not more opreating 
        /// more opeating is new and delete a txt
        /// </summary>
        /// <param name="mlist"></param>
        /// <param name="dataList"></param>
        /// <param name="isMoreOpreating"></param>
        /// <returns></returns>
        private static int CheckIsMoreOpreating(List<T_BAS_MaterialTxt> mlist, List<T_BAS_MaterialTxt> dataList, int isMoreOpreating)
        {
            isMoreOpreating += mlist.Sum(t => dataList.Count(c => t.MaterialTxtlGuid == c.MaterialTxtlGuid));
            return isMoreOpreating;
        }

        #endregion
    }
}
