using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

namespace IndieCrab
{
    public class IndieCrabRequest : MonoBehaviour
    {
        public enum CompletionState
        {
            Success,
            RetryableFailure,
            PermanentFailure
        }

        private string url = "https://www.indiecrab.com/api/log";
        private WWWForm form;
        private Action<CompletionState> onComplete;
        private bool hasStarted;

        public static IndieCrabRequest Instantiate()
        {
            GameObject go = new GameObject("IndieCrabRequest");
            IndieCrabRequest request = go.AddComponent<IndieCrabRequest>();
            return request;
        }

        private void Awake()
        {
            form = new WWWForm();
            DontDestroyOnLoad(gameObject);
        }

        public void AddField(string key, string value)
        {
            form.AddField(key, value ?? string.Empty);
        }

        public void AddOptionalField(string key, string value)
        {
            if (string.IsNullOrWhiteSpace(value)) return;
            form.AddField(key, value);
        }

        public void Send(Action<CompletionState> callback)
        {
            if (hasStarted) return;

            hasStarted = true;
            onComplete = callback;
            StartCoroutine(SendCoroutine());
        }

        private IEnumerator SendCoroutine()
        {
            if (Application.internetReachability == NetworkReachability.NotReachable)
            {
                Complete(CompletionState.RetryableFailure);
                yield break;
            }

            using (UnityWebRequest request = UnityWebRequest.Post(url, form))
            {
                yield return request.SendWebRequest();

                bool success = request.result == UnityWebRequest.Result.Success
                    && request.responseCode >= 200
                    && request.responseCode < 300;

                CompletionState completionState = CompletionState.PermanentFailure;

                if (success)
                {
                    completionState = CompletionState.Success;
                }
                else if (request.result == UnityWebRequest.Result.ConnectionError)
                {
                    completionState = CompletionState.RetryableFailure;
                }

                Complete(completionState);
            }
        }

        private void Complete(CompletionState completionState)
        {
            onComplete?.Invoke(completionState);
            Destroy(gameObject);
        }
    }
}
