using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.Extensions.Configuration;
using NMeCab;

namespace PerformanceTest
{
    internal class Program
    {
        public static IConfiguration Configuration { get; set; }

        public static void Main(string[] args = null)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddEnvironmentVariables();

            Configuration = builder.Build();

            var targetFile = Configuration["TargetFile"];
            var encoding = Encoding.GetEncoding(Configuration["TargetEncoding"]);
            var param = new MeCabParam
            {
                DicDir = @"../../dic/ipadic"
            };

            var sw = new Stopwatch();

            //開始指示を待機
            Console.WriteLine("Press Enter key to start.");
            Console.ReadLine();

            Console.WriteLine("\t\t\tProcessTime\tTotalMemory");

            //解析準備処理
            GC.Collect();
            sw.Start();
            var tagger = MeCabTagger.Create(param);
            sw.Stop();
            Console.WriteLine($"OpenTagger:\t\t{0:0.000}sec\t{1:#,000}byte",
                sw.Elapsed.TotalSeconds, GC.GetTotalMemory(false));

            //ファイル読込だけの場合
            using (var reader = new StreamReader(targetFile, encoding))
            {
                sw.Reset();
                GC.Collect();
                sw.Start();
                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                }

                sw.Stop();
            }

            Console.WriteLine("ReadLine:\t\t{0:0.000}sec\t{1:#,000}byte",
                sw.Elapsed.TotalSeconds, GC.GetTotalMemory(false));

            //解析処理（Nodeの出力）
            using (var reader = new StreamReader(targetFile, encoding))
            {
                sw.Reset();
                GC.Collect();
                sw.Start();
                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    var node = tagger.ParseToNode(line);
                }

                sw.Stop();
            }

            Console.WriteLine("ParseToNode:\t\t{0:0.000}sec\t{1:#,000}byte",
                sw.Elapsed.TotalSeconds, GC.GetTotalMemory(false));

            //解析処理（latticeモードの文字列出力）
            tagger.OutPutFormatType = "lattice";
            using (var reader = new StreamReader(targetFile, encoding))
            {
                sw.Reset();
                GC.Collect();
                sw.Start();
                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    var ret = tagger.Parse(line);
                }

                sw.Stop();
            }

            Console.WriteLine("Parse(lattice):\t\t{0:0.000}sec\t{1:#,000}byte",
                sw.Elapsed.TotalSeconds, GC.GetTotalMemory(false));


            //解析処理（Best解5件のNodeの出力）
            tagger.LatticeLevel = MeCabLatticeLevel.One;
            using (var reader = new StreamReader(targetFile, encoding))
            {
                sw.Reset();
                GC.Collect();
                sw.Start();
                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    var i = 0;
                    foreach (var node in tagger.ParseNBestToNode(line))
                        if (++i == 5)
                            break;
                }

                sw.Stop();
            }

            Console.WriteLine("ParseNBestToNode:\t{0:0.000}sec\t{1:#,000}byte",
                sw.Elapsed.TotalSeconds, GC.GetTotalMemory(false));

            //対象の情報
            using (var reader = new StreamReader(targetFile, encoding))
            {
                long charCount = 0;
                long lineCount = 0;
                long wordCount = 0;
                for (var line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    charCount += line.Length;
                    lineCount++;
                    var node = tagger.ParseToNode(line);
                    for (node = node.Next; node.Next != null; node = node.Next) wordCount++;
                }

                Console.WriteLine();
                Console.WriteLine("Target: {0} {1:#,000}byte {2:#,000}char {3:#,000}line ({4:#,000}word)",
                    targetFile, reader.BaseStream.Position, charCount, lineCount, wordCount);
            }

            tagger.Dispose();

            //終了したことを通知
            Console.WriteLine();
            Console.WriteLine("Finish!");
            Console.WriteLine("Press Enter key to close.");
            Console.ReadLine();
        }
    }
}