using System;
using System.Collections.Generic;
using System.Net;
using BestHTTP;
using LitJson;
using UnityEngine;
using UnityEngine.Events;

public class DownloadJsonFile
{
    public string rawJsonText { get; private set; }
    public JsonData jsonData { get; private set; }
    public string error { get; private set; }
    public UnityAction<DownloadJsonFile> onDownloadComplete;
    // 用于传递异步数据
    public object token;
    
    private readonly float _timeOut;
    private readonly Uri _uri;
    private bool _done;
    private HTTPRequest _request;
    private readonly Dictionary<string, string> _data;

    public DownloadJsonFile(string uri, float timeOut, Dictionary<string, string> data = null)
    {
        try
        {
            _uri = new Uri(uri);
        }
        catch (Exception e)
        {
            _uri = null;
            error = "Failed to init uri for DownloadJsonFile!\n" + e;
        }
        _data = data;
        _timeOut = timeOut;
    }

    public void Dispose(string overrideError = default(string))
    {
        if (!_done)
        {
            _done = true;
            if (_request != null)
            {
                _request.Abort();
                try
                {
                    if (_request.Response != null)
                        _request.Response.Dispose();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
                _request = null;
            }
            error = string.IsNullOrEmpty(overrideError) ? "DownloadJsonFile disposed!" : overrideError;
            if (onDownloadComplete != null)
                onDownloadComplete(this);
        }
    }

    public void Start()
    {
        if (_request == null && !_done)
        {
            if (_uri == null)
                Dispose("DownloadJsonFile uri is not correctly parsed!");
            else
            {
                if (_data == null)
                    _request = new HTTPRequest(_uri, HTTPMethods.Get);
                else
                {
                    _request = new HTTPRequest(_uri, HTTPMethods.Post);
                    foreach (var keyValue in _data)
                        _request.AddField(keyValue.Key, keyValue.Value);
                }
                _request.DisableCache = true;
                _request.Timeout = TimeSpan.FromSeconds(_timeOut);
                _request.Callback = GetResponseComplete;
                _request.Send();
            }
        }
    }

    private void GetResponseComplete(HTTPRequest originalRequest, HTTPResponse response)
    {
        if (!_done)
        {
            _done = true;
            if (response == null)
                error = "DownloadJsonFile cannot get HTTPResponse!";
            else if (!response.IsSuccess)
                error = string.Format("DownloadJsonFile Error:\n{0} - {1}", response.StatusCode,
                    response.Message);
            else
            {
                rawJsonText = response.DataAsText.Trim();
                Debug.Log("Download Text " + rawJsonText);
                try
                {
                    // 可能是404之类的错误码,因此排除10以下长度;一般格式带status, message就超过10了。
                    if (string.IsNullOrEmpty(rawJsonText) || rawJsonText.Length < 10)
                    {
                        error = "OnGetResponseComplete get a string less than 10 from the server:\n" + rawJsonText;
                    }
                    else
                    {
                        jsonData = JsonMapper.ToObject(rawJsonText);
                        error = string.Empty;
                    }
                }
                catch (WebException e)
                {
                    error = string.Format("WebException at status {0}!\n{1}", e.Status, e);
                }
                catch (Exception e)
                {
                    error = e.ToString();
                }
            }

            if (_request != null)
            {
                _request.Dispose();
                _request = null;
            }
            if (response != null)
            {
                try
                {
                    response.Dispose();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            if (onDownloadComplete != null)
                onDownloadComplete(this);
        }
    }
}