using UnityEngine;
using System.Collections;
using System.Threading;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip;
using System.IO;
using System;

namespace Giant.Common
{
	public class Unziper
	{
		public delegate void UnzipDoneDelegate(bool bOK);

		public long GetStep()
		{
			return m_uncompressSize;
		}
		public long GetMaxStep()
		{
			return m_totalSize;
		}

        public string GetCurFileName()
        {
            return m_curFileName;
        }

        void UnZipThread()
        {

        }

        public void Stop()
        {
            if(m_Thread!=null)
            {
                m_stop = true;
                for(int i = 0; i < m_Thread.Length; i ++ )
                {
                    m_Thread[i].Join();
                }
            }
        }

        public bool Unzip(string zipfilepath, string destpath, UnzipDoneDelegate onDone)
        {
            m_nStep = 0;
            //m_nMaxStep = 1;//没有用的变量 m_nMaxStep 只赋值了，但没使用  会报警告 注销掉 赋值的地方也注销 shiliang
            //ZipConstants.DefaultCodePage = 0;
            //ZipStrings.CodePage = 0;
            ZipStrings.CodePage = 0;
            var threadcount =  Environment.ProcessorCount;
           // X2Interface.LogHelper.Log("use " + threadcount + "thread unzip!");
            m_Thread = new Thread[threadcount];
            //m_startime = System.Environment.TickCount;
            for (int i = 0; i < m_Thread.Length; i++)
            {
                m_Thread[i] = new Thread(() =>
                {


                    byte[] buf = new byte[1024 * 4];
                    try
                    {

                        if (!Directory.Exists(destpath))
                        {
                            Directory.CreateDirectory(destpath);
                        }

                        using (ZipFile zipfile = new ZipFile(zipfilepath))
                        {
//                             int nentrynum = (int)zipfile.Count;
                            //m_nMaxStep = nentrynum;//没有用的变量 m_nMaxStep 只赋值了，但没使用  会报警告 注销掉 赋值的地方也注销 shiliang
                            zipfile.Close();
                        }
                            

                        using (FileStream zipfs = File.OpenRead(zipfilepath))
                        using (ZipInputStream zipStream = new ZipInputStream(zipfs))
                        {
                            m_totalSize = zipfs.Length;
                            ZipEntry entry;
                            int nCurIdx = 0;
                            while ((entry = zipStream.GetNextEntry()) != null)
                            {
                                if (m_error)
                                    return;
                                if (m_stop)
                                    return;

                                string outpath;
                                lock (this)
                                {
                                    if (nCurIdx < m_nStep)
                                    {
                                        //string value = X2Interface.Utilities.BuildString("unzip skip", nCurIdx.ToString());
                                        //X2Interface.LogHelper.Log(LogCategory.System, value);
                                        nCurIdx++;
                                        continue;
                                    }

                                    //X2Interface.LogHelper.Log("unzip" , nCurIdx, entry.Name, m_nStep);
                                    m_nStep++;

                                    nCurIdx++;


                                    outpath = Path.Combine(destpath, entry.Name);
                                    if (entry.IsDirectory)
                                    {
                                        Directory.CreateDirectory(outpath);
                                        continue;
                                    }
                                    string pathdir = Path.GetDirectoryName(outpath);
                                    if (!Directory.Exists(pathdir))
                                        Directory.CreateDirectory(pathdir);
                                    m_curFileName = entry.Name;

                                }


                                var outstream = new FileStream(outpath, FileMode.Create);

                                var startpos = zipStream.Position;
                                while (true)
                                {
                                    if (m_stop)
                                        return;

                                    int nreadsize = zipStream.Read(buf, 0, buf.Length);
                                    //m_uncompressSize = zipStream.Position > m_uncompressSize ? zipStream.Position : m_uncompressSize;
                                    long unzipsize = zipStream.Position - startpos;
                                    startpos = zipStream.Position;
                                    Interlocked.Add(ref m_uncompressSize, unzipsize);
                                    if (nreadsize > 0)
                                    {
                                        outstream.Write(buf, 0, nreadsize);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                outstream.Close();



                            }
                            zipStream.Close();
                            zipfs.Close();
                        }
                     


                    }
                    catch (Exception e)
                    {
                        lock(this)
                        {
                            if (!m_error)
                            {
                                m_error = true;
                                //lock (this) m_doneThreadCount++;
                                LogHelper.LogError(e.ToString());
                                MainThreadTask.getSingleton().push_task(() =>
                                {
                                    onDone(false);
                                });
                            }
                        }


                        return;

                    }
                    lock(this)m_doneThreadCount++;
                    if (m_doneThreadCount==m_Thread.Length)
                    {
                        //X2Interface.LogHelper.Log("unzip used:" + (System.Environment.TickCount - m_startime));
                        MainThreadTask.getSingleton().push_task(() =>
                        {
                            onDone(true);
                        });
                    }
                    

                });
                m_Thread[i].Start();
            }
           

			return true;
		}

		Thread[] m_Thread;
		private int m_nStep;
        //private int m_nMaxStep;//没有用的变量 m_nMaxStep 只赋值了，但没使用  会报警告 注销掉 赋值的地方也注销 shiliang
        int m_doneThreadCount;
        bool m_error;
        //int m_startime;
        long m_totalSize;
        long m_uncompressSize = 0;
        bool m_stop = false;
        string m_curFileName;
        //byte[] m_fileunziped;

	}

}
