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

using NLog;
using System.IO;                // FileStream
using ZeroMQ;
using ZeroMQ.Monitoring;
using System.Threading;
using System.Diagnostics;

namespace RecvProject
{
    class Program
    {
        static Logger log = LogManager.GetLogger("agent_logger");

        static void Main(string[] args)
        {
            log.Debug("Recv process start");
            Console.WriteLine("recv process start");
            String ip = args[0];
            String port = args[1];
            String home_path = args[2]+ "dat\\";

            log.Debug("ip : " + ip + ", port : " + port + ", home_path : " + home_path);

            RecvConnect(ip, port, home_path);
        }

        public static void RecvConnect(String ip, String port, String home_path)
        {
            try
            {
                ProcessFile.Files process_file = new ProcessFile.Files();
                // zeromq socket recv
                using (var socket = new ZSocket(ZSocketType.DEALER))
                {
                    log.Debug("recv listen start");

                    // socket connect
                    String conn = "tcp://" + ip + ":" + port;
                    socket.Bind(conn);  // conn listener

                    // socket monitor
                    socket.Monitor("inproc://monitor.rep", ZMonitorEvents.AllEvents);
                    Thread socketMonitorThread = new Thread(() => MonitorSocket(socket.Context));
                    socketMonitorThread.Start();

                    ZFrame frame;
                    while(true)
                    {
                        // data 수신
                        frame = socket.ReceiveFrame(ZSocketFlags.More, out ZError error);
                        byte[] buffers = frame.Read();
                        log.Debug("data receive");

                        if (!socket.ReceiveMore)
                        {
                            log.Debug("receive don't wait");

                            // messagepck desirialize 처리
                            MsgPackStruct.MsgStruct.RowListStc row_list_struct = MessagePack.MessagePackSerializer.Deserialize<MsgPackStruct.MsgStruct.RowListStc>(buffers);
                            log.Debug(row_list_struct);

                            String path = String.Format(home_path + "recv_{0}_{1}_", row_list_struct.schema, row_list_struct.table) + System.DateTime.Now.ToString("yyyyMMddHHmmss");
                            process_file.CreateFile(path + ".trc", buffers);
                            break;
                        }
                    }
                    socketMonitorThread.Join();
                }

                Thread.Sleep(2000);

                // 현재 프로세스 종료
                Process process = Process.GetCurrentProcess();
                process.Refresh();
                process.Kill();

            }
            catch (Exception e)
            {
                log.Error(e.ToString());
            }
        }

        public static void MonitorSocket(ZContext context)
        {
            // monitor 연결하고 event 결과값이 disconnect 이면 종료                                
            ZMonitor monitor = ZMonitor.Create(context, "inproc://monitor.rep");
            monitor.Start();

            monitor.AllEvents += (sender, e) =>
            {
                if (e.Event.Event == ZMonitorEvents.Disconnected)
                {
                    log.Debug("recv socket disconnected");
                }
            };
        }
    }
}
