/*
 * 由SharpDevelop创建。
 * 用户： Acer
 * 日期: 2014-10-12
 * 时间: 19:43
 * 
 */
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using System.ComponentModel;

using DataEditorX.Language;
using DataEditorX.Common;
using DataEditorX.Config;
using DataEditorX.Core.Mse;
using DataEditorX.Core.Info;
using System.Xml;

namespace DataEditorX.Core
{
	/// <summary>
	/// 任务
	/// </summary>
	public class TaskHelper
	{
		#region Member
		/// <summary>
		/// 当前任务
		/// </summary>
		private MyTask nowTask = MyTask.NONE;
		/// <summary>
		/// 上一次任务
		/// </summary>
		private MyTask lastTask = MyTask.NONE;
		/// <summary>
		/// 当前卡片列表
		/// </summary>
		private Card[] cardlist;
		/// <summary>
		/// 当前卡片列表
		/// </summary>
		public Card[] CardList
		{
			get { return this.cardlist; }
		}
		/// <summary>
		/// 任务参数
		/// </summary>
		private string[] mArgs;
		/// <summary>
		/// 图片设置
		/// </summary>
		private readonly ImageSet imgSet;
		/// <summary>
		/// MSE转换
		/// </summary>
		private readonly MseMaker mseHelper;
		/// <summary>
		/// 是否取消
		/// </summary>
		private bool isCancel = false;
		/// <summary>
		/// 是否在运行
		/// </summary>
		private bool isRun = false;
		/// <summary>
		/// 后台工作线程
		/// </summary>
		private readonly BackgroundWorker worker;

		public TaskHelper(string datapath, BackgroundWorker worker, MSEConfig mcfg)
		{
			this.Datapath = datapath;
			this.worker = worker;
            this.mseHelper = new MseMaker(mcfg);
            this.imgSet = new ImageSet();
		}
		public MseMaker MseHelper
		{
			get { return this.mseHelper; }
		}
		public bool IsRuning()
		{
			return this.isRun;
		}
		public bool IsCancel()
		{
			return this.isCancel;
		}
		public void Cancel()
		{
            this.isRun = false;
            this.isCancel = true;
		}
		public MyTask GetLastTask()
		{
			return this.lastTask;
		}
		
		public void TestPendulumText(string desc){
            this.mseHelper.TestPendulum(desc);
		}
		#endregion

		#region Other
		//设置任务
		public void SetTask(MyTask myTask, Card[] cards, params string[] args)
		{
            this.nowTask = myTask;
            this.cardlist = cards;
            this.mArgs = args;
		}
		//转换图片
		//public void ToImg(string img, string saveimg1, string saveimg2)
		public void ToImg(string img, string saveimg1)
		{
			if (!File.Exists(img))
            {
                return;
            }

            Bitmap bmp = new Bitmap(img);
			MyBitmap.SaveAsJPEG(MyBitmap.Zoom(bmp, this.imgSet.W, this.imgSet.H),
								saveimg1, this.imgSet.quilty);
			//MyBitmap.SaveAsJPEG(MyBitmap.Zoom(bmp, imgSet.w, imgSet.h),
			//					saveimg2, imgSet.quilty);
			bmp.Dispose();
		}
		#endregion

		#region 检查更新
		public static void CheckVersion(bool showNew)
		{
			string newver = CheckUpdate.GetNewVersion(MyConfig.ReadString(MyConfig.TAG_UPDATE_URL));
			if (newver == CheckUpdate.DEFAULT)
			{   //检查失败
				if (!showNew)
                {
                    return;
                }

                MyMsg.Error(LMSG.CheckUpdateFail);
				return;
			}

			if (CheckUpdate.CheckVersion(newver, Application.ProductVersion))
			{//有最新版本
				if (!MyMsg.Question(LMSG.HaveNewVersion))
                {
                    return;
                }
            }
			else
			{//现在就是最新版本
				if (!showNew)
                {
                    return;
                }

                if (!MyMsg.Question(LMSG.NowIsNewVersion))
                {
                    return;
                }
            }
			//下载文件
			if (CheckUpdate.DownLoad(
				MyPath.Combine(Application.StartupPath, newver + ".zip")))
            {
                MyMsg.Show(LMSG.DownloadSucceed);
            }
            else
            {
                MyMsg.Show(LMSG.DownloadFail);
            }
        }
		public void OnCheckUpdate(bool showNew)
		{
			TaskHelper.CheckVersion(showNew);
		}
		#endregion

		#region 裁剪图片
		public void CutImages(string imgpath, bool isreplace)
		{
			int count = this.cardlist.Length;
			int i = 0;
			foreach (Card c in this.cardlist)
			{
				if (this.isCancel)
                {
                    break;
                }

                i++;
                this.worker.ReportProgress((i / count), string.Format("{0}/{1}", i, count));
				string jpg = MyPath.Combine(imgpath, c.id + ".jpg");
				string savejpg = MyPath.Combine(this.mseHelper.ImagePath, c.id + ".jpg");
				if (File.Exists(jpg) && (isreplace || !File.Exists(savejpg)))
				{
					Bitmap bp = new Bitmap(jpg);
                    Bitmap bmp;
                    if (c.IsType(CardType.TYPE_XYZ))//超量
					{
						bmp = MyBitmap.Cut(bp, this.imgSet.xyzArea);
					}
					else if (c.IsType(CardType.TYPE_PENDULUM))//P怪兽
					{
						bmp = MyBitmap.Cut(bp, this.imgSet.pendulumArea);
					}
					else//一般
					{
						bmp = MyBitmap.Cut(bp, this.imgSet.normalArea);
					}
					bp.Dispose();
					MyBitmap.SaveAsJPEG(bmp, savejpg, this.imgSet.quilty);
					//bmp.Save(savejpg, ImageFormat.Png);
				}
			}
		}
		#endregion
		
		//removed thumbnail
		#region 转换图片
		public void ConvertImages(string imgpath, string gamepath, bool isreplace)
		{
			string picspath = MyPath.Combine(gamepath, "pics");
			//string thubpath = MyPath.Combine(picspath, "thumbnail");
			string[] files = Directory.GetFiles(imgpath);
			int i = 0;
			int count = files.Length;

			foreach (string f in files)
			{
				if (this.isCancel)
                {
                    break;
                }

                i++;
                this.worker.ReportProgress(i / count, string.Format("{0}/{1}", i, count));
				string ex = Path.GetExtension(f).ToLower();
				string name = Path.GetFileNameWithoutExtension(f);
				string jpg_b = MyPath.Combine(picspath, name + ".jpg");
				//string jpg_s = MyPath.Combine(thubpath, name + ".jpg");
				if (ex == ".jpg" || ex == ".png" || ex == ".bmp")
				{
					if (File.Exists(f))
					{
						Bitmap bmp = new Bitmap(f);
						//大图，如果替换，或者不存在
						if (isreplace || !File.Exists(jpg_b))
						{

							MyBitmap.SaveAsJPEG(MyBitmap.Zoom(bmp, this.imgSet.W, this.imgSet.H),
							                    jpg_b, this.imgSet.quilty);
						}
						//小图，如果替换，或者不存在
						//if (isreplace || !File.Exists(jpg_s))
						//{
						//	MyBitmap.SaveAsJPEG(MyBitmap.Zoom(bmp, imgSet.w, imgSet.h),
						//						jpg_s, imgSet.quilty);

						//}
					}
				}
			}
		}
		#endregion

		#region MSE存档
		public string MSEImagePath
		{
			get { return this.mseHelper.ImagePath; }
		}

		public string Datapath { get; }

		public void SaveMSEs(string file, Card[] cards,bool isUpdate)
		{
			if(cards == null)
            {
                return;
            }

            string pack_db=MyPath.GetRealPath(MyConfig.ReadString("pack_db"));
			bool rarity=MyConfig.ReadBoolean("mse_auto_rarity", false);
			#if DEBUG
			MessageBox.Show("db = "+pack_db+",auto rarity="+rarity);
			#endif
			int c = cards.Length;
			//不分开，或者卡片数小于单个存档的最大值
			if (this.mseHelper.MaxNum == 0 || c < this.mseHelper.MaxNum)
            {
                this.SaveMSE(1, file, cards,pack_db, rarity, isUpdate);
            }
            else
			{
				int nums = c / this.mseHelper.MaxNum;
				if (nums * this.mseHelper.MaxNum < c)//计算需要分多少个存档
                {
                    nums++;
                }

                List<Card> clist = new List<Card>();
				for (int i = 0; i < nums; i++)//分别生成存档
				{
					clist.Clear();
					for (int j = 0; j < this.mseHelper.MaxNum; j++)
					{
						int index = i * this.mseHelper.MaxNum + j;
						if (index < c)
                        {
                            clist.Add(cards[index]);
                        }
                    }
					int t = file.LastIndexOf(".mse-set");
					string fname = (t > 0) ? file.Substring(0, t) : file;
					fname += string.Format("_{0}.mse-set", i + 1);
                    this.SaveMSE(i + 1, fname, clist.ToArray(),pack_db, rarity, isUpdate);
				}
			}
		}
		public void SaveMSE(int num, string file, Card[] cards,string pack_db,bool rarity, bool isUpdate)
		{
			string setFile = file + ".txt";
			Dictionary<Card, string> images = this.mseHelper.WriteSet(setFile, cards,pack_db,rarity);
			if (isUpdate)//仅更新文字
            {
                return;
            }

            int i = 0;
			int count = images.Count;
			using (ZipStorer zips = ZipStorer.Create(file, ""))
			{
				zips.EncodeUTF8 = true;//zip里面的文件名为utf8
				zips.AddFile(setFile, "set", "");
				foreach (Card c in images.Keys)
				{
					string img=images[c];
					if (this.isCancel)
                    {
                        break;
                    }

                    i++;
                    this.worker.ReportProgress(i / count, string.Format("{0}/{1}-{2}", i, count, num));
					//TODO 先裁剪图片
					zips.AddFile(this.mseHelper.GetImageCache(img,c), Path.GetFileName(img), "");
				}
			}
			File.Delete(setFile);
		}
		public Card[] ReadMSE(string mseset, bool repalceOld)
		{
			//解压所有文件
			using (ZipStorer zips = ZipStorer.Open(mseset,FileAccess.Read))
			{
				zips.EncodeUTF8 = true;
				List<ZipStorer.ZipFileEntry> files = zips.ReadCentralDir();
				int count = files.Count;
				int i = 0;
				foreach (ZipStorer.ZipFileEntry file in files)
				{
                    this.worker.ReportProgress(i / count, string.Format("{0}/{1}", i, count));
					string savefilename = MyPath.Combine(this.mseHelper.ImagePath, file.FilenameInZip);
					zips.ExtractFile(file, savefilename);
				}
			}
			string setfile = MyPath.Combine(this.mseHelper.ImagePath, "set");
			return this.mseHelper.ReadCards(setfile, repalceOld);
		}
		#endregion

		#region 导出数据
		public void ExportData(string path, string zipname, string _cdbfile, string modulescript)
		{
			int i = 0;
			Card[] cards = this.cardlist;
			if (cards == null || cards.Length == 0)
            {
                return;
            }

            int count = cards.Length;
			YgoPath ygopath = new YgoPath(path);
			string name = Path.GetFileNameWithoutExtension(zipname);
			//数据库
			string cdbfile = zipname + ".cdb";
			//说明
			string readme = MyPath.Combine(path, name + ".txt");
			//新卡ydk
			string deckydk = ygopath.GetYdk(name);
			//module scripts
			string extra_script = "";
			if (modulescript.Length > 0)
            {
                extra_script = ygopath.GetModuleScript(modulescript);
            }

            File.Delete(cdbfile);
			DataBase.Create(cdbfile);
			DataBase.CopyDB(cdbfile, false, this.cardlist);
			if (File.Exists(zipname))
            {
                File.Delete(zipname);
            }

            using (ZipStorer zips = ZipStorer.Create(zipname, ""))
			{
				zips.AddFile(cdbfile,  Path.GetFileNameWithoutExtension(_cdbfile) + ".cdb", "");
				if (File.Exists(readme))
                {
                    zips.AddFile(readme, "readme_" + name + ".txt", "");
                }

                if (File.Exists(deckydk))
                {
                    zips.AddFile(deckydk, "deck/" + name + ".ydk", "");
                }

                if (modulescript.Length > 0 && File.Exists(extra_script))
                {
                    zips.AddFile(extra_script, extra_script.Replace(path, ""), "");
                }

                foreach (Card c in cards)
				{
					i++;
                    this.worker.ReportProgress(i / count, string.Format("{0}/{1}", i, count));
					string[] files = ygopath.GetCardfiles(c.id);
					foreach (string file in files)
					{
						if (!string.Equals(file, extra_script) && File.Exists(file))
						{
							zips.AddFile(file, file.Replace(path,""), "");
						}
					}
				}
			}
			File.Delete(cdbfile);
		}
		#endregion

		#region 运行
		public void Run()
		{
            this.isCancel = false;
            this.isRun = true;
			bool replace;
			bool showNew;
			switch (this.nowTask)
			{
				case MyTask.ExportData:
					if (this.mArgs != null && this.mArgs.Length >= 3)
					{
                        this.ExportData(this.mArgs[0], this.mArgs[1], this.mArgs[2], this.mArgs[3]);
					}
					break;
				case MyTask.CheckUpdate:
					showNew = false;
					if (this.mArgs != null && this.mArgs.Length >= 1)
					{
						showNew = (this.mArgs[0] == bool.TrueString) ? true : false;
					}
                    this.OnCheckUpdate(showNew);
					break;
				case MyTask.CutImages:
					if (this.mArgs != null && this.mArgs.Length >= 2)
					{
						replace = true;
						if (this.mArgs.Length >= 2)
						{
							if (this.mArgs[1] == bool.FalseString)
                            {
                                replace = false;
                            }
                        }
                        this.CutImages(this.mArgs[0], replace);
					}
					break;
				case MyTask.SaveAsMSE:
					if (this.mArgs != null && this.mArgs.Length >= 2)
					{
						replace = false;
						if (this.mArgs.Length >= 2)
						{
							if (this.mArgs[1] == bool.TrueString)
                            {
                                replace = true;
                            }
                        }
                        this.SaveMSEs(this.mArgs[0], this.cardlist, replace);
					}
					break;
				case MyTask.ReadMSE:
					if (this.mArgs != null && this.mArgs.Length >= 2)
					{
						replace = false;
						if (this.mArgs.Length >= 2)
						{
							if (this.mArgs[1] == bool.TrueString)
                            {
                                replace = true;
                            }
                        }
                        this.cardlist = this.ReadMSE(this.mArgs[0], replace);
					}
					break;
				case MyTask.ConvertImages:
					if (this.mArgs != null && this.mArgs.Length >= 2)
					{
						replace = true;
						if (this.mArgs.Length >= 3)
						{
							if (this.mArgs[2] == bool.FalseString)
                            {
                                replace = false;
                            }
                        }
                        this.ConvertImages(this.mArgs[0], this.mArgs[1], replace);
					}
					break;
			}
            this.isRun = false;
            this.lastTask = this.nowTask;
            this.nowTask = MyTask.NONE;
			if(this.lastTask != MyTask.ReadMSE)
            {
                this.cardlist = null;
            }

            this.mArgs = null;
		}
		#endregion
	}

}
