using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;

namespace JtkManagerClient {
    static class Program {
        public static Uri WebApiUri;
        public static string PcId;
        public static int AuthorizationKey;
        public static double FarePerHour;
        //public static readonly Dictionary<string, (int number, int row, int column)> PcMap = new Dictionary<string, (int number, int row, int column)>();
        /// <summary>
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // PC Map을 Settings로부터 불러와 적용
            //UpdatePcStructure(Properties.Settings.Default.PcMap);
            
            var loginForm = new LoginForm();
            Application.Run(loginForm);
            if (loginForm.DialogResult != DialogResult.OK) {
                return;
            }
            
            var mainForm = new MainForm();
            Application.Run(mainForm);
        }

        /// <summary>
        /// 직렬화된 JSON 문자열로 PC Map을 갱신합니다.
        /// </summary>
        //static void UpdatePcStructure(string json) {
        //    foreach (var pair in JObject.Parse(json)) {
        //        PcMap[pair.Key] = (
        //            number: pair.Value["num"].ToObject<int>(),
        //            row: pair.Value["row"].ToObject<int>(),
        //            column: pair.Value["col"].ToObject<int>()
        //        );
        //    }
        //}


        
        private static readonly object requestLocker = new object();
        private static readonly CookieContainer cookieContainer = new CookieContainer();
        /// <summary>
        /// 로컬 서버에 HTTP 요청을 합니다. 전달된 JObject 객체를 POST 메서드로 Body에 담아 보냅니다. PC ID와 허가 키는 자동으로 포함됩니다.
        /// </summary>
        /// <param name="requestJObject">Body에 담길 JObject 객체</param>
        public static Task<JObject> GetPostResponseAsync(JObject requestJObject) =>
            Task.Factory.StartNew(obj => {
                try {
                    lock (requestLocker) {
                        var jObject = obj as JObject;
                        jObject["auth_key"] = AuthorizationKey;
                        jObject["pc_id"] = PcId;

                        // 요청 준비
                        HttpWebRequest request = WebRequest.Create(WebApiUri) as HttpWebRequest;
                        request.CookieContainer = cookieContainer;
                        request.Method = "POST";
                        var requestBuffer = Encoding.UTF8.GetBytes(jObject.ToString());
                        request.ContentLength = requestBuffer.Length;
                        request.ContentType = "application/x-www-form-urlencoded";
                        using (var stream = request.GetRequestStream()) {
                            stream.Write(requestBuffer, 0, requestBuffer.Length);
                        }

                        // 응답 받기
                        string result;
                        using (var response = request.GetResponse()) {
                            if (response.ContentLength <= 0) {
                                return null;
                            }
                            var responseBuffer = new byte[response.ContentLength];
                            using (var stream = response.GetResponseStream()) {
                                using (var reader = new StreamReader(stream)) {
                                    result = reader.ReadToEnd();
                                }
                            }
                        }
                        return JObject.Parse(result);
                    }
                } catch /*(Exception e)*/ {
                    return null;
                }
            }, requestJObject);
        /// <summary>
        /// 로컬 서버에 HTTP 요청을 합니다. 전달된 객체를 JSON으로 직렬화하여 POST 메서드로 Body에 담아 보냅니다. PC ID와 허가 키는 자동으로 포함됩니다.
        /// </summary>
        /// <param name="requestJObject">JSON으로 직렬화되어 Body에 담길 객체</param>
        public static Task<JObject> GetPostResponseAsync(object requestObject) {
            try { return GetPostResponseAsync(JObject.FromObject(requestObject)); } catch { return null; }
        }
    }
}
