using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.SqlClient;    // SqlCommand

using NLog;
using ZeroMQ;
using System.Threading;
using Newtonsoft.Json;

namespace ProcessSocket
{
    public class SocketProcess
    {
        static Logger log = LogManager.GetLogger("target_logger");
        public String TargetSocket(string port, SqlConnection connection)
        {
            log.Debug("Process socket start");
            String other_process_status = "";
            try
            {
                ProcessDatabase.ProcessDB process_database = new ProcessDatabase.ProcessDB();
                ProcessDatabase.Struct.CmdStruct cmd_struct = new ProcessDatabase.Struct.CmdStruct();
                ProcessDatabase.Struct.DataStruct data_struct = new ProcessDatabase.Struct.DataStruct();
                ProcessDatabase.Struct.ExecuteResultStruct result_struct = new ProcessDatabase.Struct.ExecuteResultStruct();

                List<string> request_list = new List<string>();

                // socket create
                using (var socket = new ZSocket(ZSocketType.REP))
                {
                    log.Debug("socket create");
                    // socket connection
                    string conn = string.Format("tcp://172.16.10.63:{0}", port);
                    // socket bind
                    socket.Bind(conn);
                    log.Debug("socket bind");

                    // 다른 process 접속 대기
                    Console.WriteLine("other socket connection waiting\n");
                    log.Debug("other socket connection waiting");

                    while (true)
                    {
                        // receive
                        using (ZFrame frame = socket.ReceiveFrame())
                        {
                            string request = frame.ReadString();

                            Thread.Sleep(1000);
                            request_list.Add(request);

                            if (!socket.ReceiveMore)
                            {
                                log.Debug("multipart no receive more");
                                List<ProcessDatabase.Struct.DataStruct> data_list = new List<ProcessDatabase.Struct.DataStruct>();
                                log.Debug("request parsing and convert struct");
                                for (int i = 0; i < request_list.Count; i++)
                                {
                                    if(request_list[i] != "exit")
                                    {
                                        // request parsing and convert struct
                                        data_struct = JsonConvert.DeserializeObject<ProcessDatabase.Struct.DataStruct>(request_list[i]);
                                        data_list.Add(data_struct);
                                    } else
                                    {
                                        other_process_status = "exit";
                                    }
                                }

                                // create and excute query
                                cmd_struct = process_database.CreateQuery(data_list);

                                // excute 결과 누적
                                result_struct = process_database.ExcuteQuery(cmd_struct, connection);
                                request_list = new List<string>();

                                // 결과 전송
                                log.Debug("send excute query result");
                                String excute_result = JsonConvert.SerializeObject(result_struct, Formatting.None);
                                Console.WriteLine("excute_result : " + excute_result);
                                socket.Send(new ZFrame(excute_result), ZSocketFlags.DontWait);
                            }
                        }

                        if(other_process_status == "exit")
                        {
                            break;
                        }
                    }
                }
            } catch(Exception e)
            {
                log.Error(e.ToString());
            }

            log.Debug("Process socket end");
            return other_process_status;
        }
    }
}
