using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;
using System.Collections.Concurrent;
 
 
namespace dns_log_parser
{
    class Program
    {
 
        static long offset = 0;
        //static FileStream file;
        static StreamReader reader;
 
        static ConcurrentDictionary<(stringstring), int> dnsstat = new ConcurrentDictionary<(stringstring), int>();
        static void Main(string[] args)
        {
            if (args.Count() < 1) {
                Console.WriteLine("Usage: dns_log_parser.exe [path_to_log]");
                Environment.Exit(0);
            }
 
            string sourceFile = args[0];
 
            if (!File.Exists(sourceFile))
            {
                Console.WriteLine("{0} not exist", sourceFile);
                Environment.Exit(0);
            }
 
            offset = (new FileInfo(sourceFile)).Length;
 
            Timer t = new Timer(TimerCallback, null, 0, 2000);
 
            while (true)
            {
                FileStream file = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                var info = new FileInfo(sourceFile);
                if (info.Length < offset)
                    offset = 0;
                using (new StreamReader(file))
                {
                    file.Seek(offset, SeekOrigin.Begin);
                    reader = new StreamReader(file);
 
                    file.Seek(offset, SeekOrigin.Begin);
                    if (!reader.EndOfStream)
                    {
                        do
                        {
                            string line = reader.ReadLine();
                            // ^.+Rcv\s+([0-9\.]+)\s+([0-9A-Fa-f]+)\s+.+\[.+\]\s+(\w+)\s+\(\d\)(.+)\(0\)$
                            // https://answers.splunk.com/answers/132364/dns-debug-log-dns-log-format-review.html
                            Regex regex = new Regex(@"^.+Rcv\s+([0-9\.]+)\s+([0-9A-Fa-f]+)\s+.+\[.+\]\s+(\w+)\s+\(\d\)(.+)\(0\)$");
 
                            Match match = regex.Match(line);
                            if (match.Success)
                            {
                                string ip = match.Groups[1].Value;
                                //string dsthost = match.Groups[4].Value;
                                string dsthost = Regex.Replace(match.Groups[4].Value, @"\(\d+\)+"".");
 
                                int curcount;
                                if (dnsstat.TryGetValue((ip, dsthost), out curcount))
                                {
                                    dnsstat[(ip, dsthost)] = curcount + 1;
                                    if (curcount % 10 == 0)
                                    {
                                        //Console.WriteLine("ip: {0} dns: {1} count: {2}", ip, dsthost, curcount);
                                    }
                                }
                                else
                                {
                                    dnsstat.TryAdd((ip, dsthost), 1);
                                }
 
                                //Console.WriteLine("{0} {1}", ip, dsthost);
                            }
                               
                        while (!reader.EndOfStream);
 
                        offset = file.Position;
                        //Console.WriteLine("{0}", offset);
                    }
                    reader.Close();
                    Thread.Sleep(100);
                }
            }
        }
        private static void TimerCallback(Object o)
        {
            ConcurrentDictionary<(stringstring), int> dnsstatviewtemp = dnsstat;
 
            var dnsstatview = dnsstatviewtemp.OrderByDescending(x => x.Value).Take(50);
 
            Console.Clear();
 
            foreach (KeyValuePair<(stringstring), int> item in dnsstatview)
            {
                Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
 
            }
 
        }
    }
}