using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;

public class Downloader
{
    private Stream mFs, mNs;
    private byte[] mBuff;
    private HotUpdater.PackageInfo mPackageInfo = null;

    /// <summary>
    /// 下载状态
    /// </summary>
    public DownloadState state { get; private set; }
    /// <summary>
    /// 当前已下载大小
    /// </summary>
    public long curDownloadSize { get; private set; }
    /// <summary>
    /// 停止线程
    /// </summary>
    private bool mStopThread = false;
    private Thread mThread;

    public void Start(HotUpdater.PackageInfo packageInfo)
    {
        // 下载块大小
        // mBuff = new byte[1024*4];
        mBuff = new byte[64];
        state = DownloadState.Ready;
        mPackageInfo = packageInfo;
        var httpReq = HttpWebRequest.Create(mPackageInfo.url) as HttpWebRequest;
        httpReq.Timeout = 5000;
        // 以MD5作为文件名保存文件
        var savePath = Application.persistentDataPath + "/" + mPackageInfo.md5;
        GameLogger.LogGreen("DownloadManager Start, savePath = " + savePath);
        mFs = new FileStream(savePath, FileMode.OpenOrCreate, FileAccess.Write);
        curDownloadSize = mFs.Length;

        if (curDownloadSize == mPackageInfo.size)
        {
            // 已下载完毕，释放下载进程
            state = DownloadState.End;
            Dispose();
            return;
        }
        else if (curDownloadSize > 0)
        {
            GameLogger.LogGreen("检测到上次下载未结束，断点续传，上次已下载大小：" + curDownloadSize);
            // 设置本地文件流的起始位置
            mFs.Seek(curDownloadSize, SeekOrigin.Current);
            // 设置远程访问文件流的起始位置
            httpReq.AddRange(curDownloadSize);
        }

        HttpWebResponse response;
        try
        {
            response = (HttpWebResponse)httpReq.GetResponse();
        }
        catch (System.Exception e)
        {
            // 发生异常，连接失败
            GameLogger.LogError(e);
            state = DownloadState.ConnectionError;
            return;
        }

        GameLogger.Log("response.StatusCode = " + response.StatusCode);
        if (response.StatusCode != HttpStatusCode.PartialContent)
        {
            // 断点续传
            if (File.Exists(savePath))
            {
                mFs.Close();
                mFs = null;
                curDownloadSize = 0;
                File.Delete(savePath);
            }
            mFs = new FileStream(savePath, FileMode.Create, FileAccess.Write);
        }

        mNs = response.GetResponseStream();
        // 开启一个新的写文件进程
        if (null == mThread)
        {
            mStopThread = false;
            mThread = new Thread(WriteThread);
            mThread.Start();
        }
    }

    /// <summary>
    /// 写文件进程
    /// </summary>
    private void WriteThread()
    {
        state = DownloadState.Ing;
        while (!mStopThread)
        {
            try
            {
                var readSize = mNs.Read(mBuff, 0, mBuff.Length);
                if (readSize > 0)
                {
                    mFs.Write(mBuff, 0, readSize);
                    curDownloadSize += readSize;
                    Thread.Sleep(0);
                }
                else
                {
                    // 完毕
                    mStopThread = true;
                    state = DownloadState.End;
                    Dispose();
                }
            }
            catch (System.Exception e)
            {
                // 下载出错
                GameLogger.LogError(e);
                state = DownloadState.DataProcessingError;
                Dispose();
            }
        }
    }

    /// <summary>
    /// 清理
    /// </summary>
    public void Dispose()
    {
        mStopThread = true;
        if (null != mFs)
        {
            mFs.Close();
            mFs = null;
        }
        if (null != mNs)
        {
            mNs.Close();
            mNs = null;
        }
        mPackageInfo = null;
        mBuff = null;
    }

    public enum DownloadState
    {
        Ready,
        Ing,
        ConnectionError,
        DataProcessingError,
        End,
    }
}