tomazsaraiva
7/31/2018 - 1:55 PM

Rest Service

public class RestService : RestServiceBase
{
    // ctor

    public RestService(string host) : base(host)
    {

    }


    // RestServiceBase

    protected override void OnResponse(object sender, WVF.REST.RestService.Response e)
    {
        base.OnResponse(sender, e);

        if (e.Request.Callback != null)
        {
            CrossCurrentActivity.Current.Activity.RunOnUiThread(() =>
            {
                e.Request.Callback.Invoke(e.Result);
                e.Request.Dispose();
            });
        }
    }
}
public class RestServiceBase
{
    // fields

    RestService _service;


    // ctor

    public RestServiceBase(string host)
    {
        _service = new RestService(host);
        _service.OnResponse += OnResponse;
    }


    // RestServiceBase

    public void MakeRequest(Request request)
    {
        _service.MakeRequest(request);
    }

    protected virtual void OnResponse(object sender, RestService.Response e)
    {

    }


    // IDisposable

    public void Dispose()
    {
        _service.OnResponse -= OnResponse;
        _service.Dispose();
        _service = null;
    }
}
public class ResultCache
{
    // properties

    public string Id
    {
        get;
        private set;
    }

    public Result Result
    {
        get;
        private set;
    }

    public DateTime Timestamp
    {
        get;
        private set;
    }


    // ctor

    public ResultCache(string id, Result result)
    {
        Id = id;
        Result = result;
        Timestamp = DateTime.Now;
    }
}
public class Result
{
    // properties

    public bool Success
    {
        get;
        protected set;
    }

    public JObject Data
    {
        get;
        protected set;
    }

    public string Error
    {
        get;
        set;
    }


    // ctor

    public Result(JObject jObject)
    {
        int status = JSON.GetInt(jObject, "status");

        Success = status == 0;
        Data = jObject;

        if (!Success)
        {
            Error = JSON.GetString(jObject, "error");
        }
    }

    public Result(string error)
    {
        Success = false;
        Error = error;
    }
}
public class Request : IDisposable
{
    // delegates

    public delegate void RequestResult(Result result);


    // properties

    public string Id
    {
        get
        {
            return RestRequest.Resource;
        }
    }

    public bool Cache
    {
        get;
        private set;
    }

    public RestRequest RestRequest
    {
        get;
        private set;
    }

    public RequestResult Callback
    {
        get;
        private set;
    }

    public RestRequestAsyncHandle Handler
    {
        get;
        set;
    }

    public int Tries
    {
        get;
        set;
    }



    // ctor

    public Request(RestRequest restRequest, RequestResult callback)
    {
        RestRequest = restRequest;
        Callback = callback;
    }

    public Request(RestRequest restRequest, RequestResult callback, bool cache) : this(restRequest, callback)
    {
        Cache = cache;
    }


    // IDisposable

    public void Dispose()
    {
        Tries = 0;
        Handler = null;
        Callback = null;
    }
}
public class RestService : IDisposable
{
    public class Response : EventArgs
    {
        // properties

        public Request Request
        {
            get;
            private set;
        }

        public Result Result
        {
            get;
            private set;
        }


        // ctor

        public Response(Request request, Result result)
        {
            Request = request;
            Result = result;
        }
    }


    // events

    public EventHandler<Response> OnResponse;


    // consts

    const int MAX_TRIES = 3;


    // fields

    RestClient _client;

    Dictionary<string, ResultCache> _cache;


    // ctor

    public RestService(string host)
    {
        _client = new RestClient(host);
    }


    // Rest Service

    public void MakeRequest(Request request)
    {
        if (UseCache(request))
        {
            Console.Writeline("Request from Cache | " + request.RestRequest.Resource);

            InvokeResult(request, _cache[request.Id].Result);

            return;
        }

        request.Handler = Request(request.RestRequest, (success, content) =>
        {
            if (success && (request.Cache || request.Callback != null))
            {
                Console.Writeline("Request SUCCESS | " + content);

                Result result = new Result(JObject.Parse(content));

                if (request.Cache)
                {
                    CacheResult(request, result);
                }

                InvokeResult(request, result);

                return;
            }

            if (request.Callback == null)
            {
                return;
            }

            if (request.Tries < MAX_TRIES)
            {
                Console.Writeline("Request Retry | " + request.Tries);

                request.Tries++;

                MakeRequest(request);

                return;
            }

            Console.Writeline("Request FAIL | " + content);

            InvokeResult(request, new Result(content));
        });
    }

    void InvokeResult(Request request, Result result)
    {
        if (OnResponse != null)
        {
            OnResponse.Invoke(this, new Response(request, result));
        }
    }


    delegate void RequestResult(bool success, string content);

    RestRequestAsyncHandle Request(RestRequest request, RequestResult callback)
    {
        bool connected = ConnectionManager.Instance.IsConnected;

        if (connected)
        {
            Console.Writeline("Request | " + request.Resource);

            return _client.ExecuteAsync(request, response =>
            {
                if (callback != null)
                {
                    if (response.ErrorException == null)
                    {
                        callback.Invoke(true, response.Content);
                    }
                    else
                    {
                        callback.Invoke(false, response.ErrorMessage);
                    }

                    callback = null;
                }
            });
        }

        callback.Invoke(false, "No Internet Connection");

        return null;
    }


    bool UseCache(Request request)
    {
        return request.Cache && _cache != null && _cache.ContainsKey(request.Id);
    }

    void CacheResult(Request request, Result result)
    {
        if (_cache == null)
        {
            _cache = new Dictionary<string, ResultCache>();
        }

        ResultCache cache = new ResultCache(request.Id, result);

        if (!_cache.ContainsKey(request.Id))
        {
            _cache.Add(cache.Id, cache);
        }
        else
        {
            _cache[request.Id] = cache;
        }
    }


    public void ClearCache()
    {
        Console.Writeline("Clearing Cache");

        if (_cache != null)
        {
            _cache.Clear();
        }
    }


    // IDisposable

    public void Dispose()
    {
        OnResponse = null;

        if (_cache != null)
        {
            _cache.Clear();
            _cache = null;
        }
    }
}