using Forks.JsonRpc.Client;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ButcherFactory.BO.Utils
{
  public class ClientRpc
  {
    public ClientRpc(string url)
    {
      mUrl = url;
    }

    class _Error
    {
      public int? code { get; set; }
      public string message { get; set; }
    }
    class _ErrorResposne
    {
      public _Error error { get; set; }
    }

    string mUrl;

    public string Url
    {
      get
      {
        return mUrl;
      }
    }

    public T Call<T>(string method, params object[] args)
    {
      var resp = DoCall<T>(method, args);

      if (resp.error != null)
      {
        throw new Exception(string.Format("{0}:{1}", resp.error.code, resp.error.message));
      }

      return resp.result;
    }

    LRestClientReponse<T> DoCall<T>(string method, object[] args)
    {
      var request = (HttpWebRequest)WebRequest.Create(mUrl);
      request.Method = "POST";
      request.ContentType = "application/json";
      var dic = new Dictionary<string, object>();
      dic.Add("method", method);
      dic.Add("id", 1);
      dic.Add("params", args);

      var json = JsonConvert.SerializeObject(dic);

      var buffer = Encoding.UTF8.GetBytes(json);

      var requestStream = request.GetRequestStream();
      requestStream.Write(buffer, 0, buffer.Length);

      var responseJson = GetResponseJSON(request);

      try
      {
        var result = JsonConvert.DeserializeObject<LRestClientReponse<T>>(responseJson);
        return result;
      }
      catch
      {
        try
        {
          var errorResponse = JsonConvert.DeserializeObject<_ErrorResposne>(responseJson);
          if (errorResponse.error != null)
          {
            throw new JsonRpcException(errorResponse.error.message);
          }
        }
        catch
        {
          throw new Exception("JSON反序列化失败:" + responseJson);
        }
        throw new Exception("JSON反序列化失败:" + responseJson);
      }

    }

    public class LRestClientReponseError
    {
      public string code { get; set; }
      public string message { get; set; }

      public override string ToString()
      {
        return string.Format("{0}:{1}", code, message);
      }
    }

    public class LRestClientReponse<T>
    {
      public long id { get; set; }
      public LRestClientReponseError error { get; set; }
      public T result { get; set; }
    }

    private static string GetResponseJSON(HttpWebRequest request)
    {
      var response = request.GetResponse();
      using (var stream = response.GetResponseStream())
      {
        using (var reader = new StreamReader(stream, Encoding.UTF8))
        {
          return reader.ReadToEnd();
        }
      }
    }
  }
}
