using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using JtkLibrary;
using Newtonsoft.Json.Linq;
using WebSocketManager = JtkLibrary.WebSocketManager;

namespace JtkManagerClient {
    public partial class LoginForm : Form {
        public LoginForm() {
            InitializeComponent();
        }

        private async void ConnectButton_Click(dynamic sender, EventArgs e) {
            sender.Enabled = false;
            connectionGroupBox.Enabled = false;
            this.Cursor = Cursors.AppStarting;
            var pcId = Program.PcId = PcIdTextBox.Text;
            var webSocketUri = new Uri($"ws://{AddressTextBox.Text}:5000/ws");
            var webApiUri = Program.WebApiUri = new Uri($"http://{AddressTextBox.Text}:5000/api");
            var webSocket = new ClientWebSocket();
            
            try {
                // 로컬서버와 웹소켓 연결
                await webSocket.ConnectAsync(webSocketUri, new CancellationTokenSource(5000).Token);
                if (webSocket.State != WebSocketState.Open) {
                    throw new Exception("Failed to connect to the server.");
                }
                // 인증 정보 송신
                var sendBuffer = Encoding.UTF8.GetBytes(JObject.FromObject(new { pc_id = pcId, agent = "manager" }).ToString());
                webSocket.SendAsync(new ArraySegment<byte>(sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None).Wait();
                // 인증 결과 수신
                var receiveBuffer = new byte[1024];
                var receiveTask = webSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None);
                receiveTask.Wait();
                var receiveResult = receiveTask.Result;
                // 거부되었나 확인
                if (receiveResult.CloseStatus != null) {
                    throw new Exception(receiveResult.CloseStatusDescription);
                }
                // 유효하지 않은 결과인지 확인
                if (receiveResult.MessageType != WebSocketMessageType.Text || receiveResult.EndOfMessage == false) {
                    throw new Exception("Received invalid data.");
                }
                // 결과 JSON 파싱
                var receiveText = Encoding.UTF8.GetString(receiveBuffer);
                var receiveJObject = JObject.Parse(receiveText);
                // ok 아닐 시
                if (receiveJObject.GetValue("result").ToString() != "ok") {
                    throw new Exception("The response is not ok.");
                }
                Program.PcId = pcId;
                // 허가키 획득 (세션없이 HTTP 통신 위해)
                Program.AuthorizationKey = receiveJObject.GetValue("auth_key").ToObject<int>();
                // FarePerHour
                Program.FarePerHour = receiveJObject.GetValue("fare_per_hour").ToObject<double>();
                // 수신 루프 구성
                var loop = WebSocketManager.AddAndLoop(string.Empty, webSocket);
                // 성공
                DialogResult = DialogResult.OK;
                Close();
            } catch (Exception exc) {
                this.Cursor = Cursors.Default;
                MessageBox.Show(exc.Message);
                connectionGroupBox.Enabled = true;
                sender.Enabled = true;
            }
        }
    }
}
