// Created with MonoDevelop
//
//    Copyright (C) 2017 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.




using System;
using System.IO;
using System.Text;
using System.Collections.Generic;

namespace Hiperscan.FileIO
{
	public partial class LogWriter : StringWriter, IDisposable
	{
		public static LogWriter Current {get; set;}
		
		public LogWriter(string log_file, double max_size_in_mb)
		{
			this.MaxSize = max_size_in_mb;
			
			string file = Path.GetFileNameWithoutExtension(log_file);
			string extension = Path.GetExtension(log_file);
			
			string path = Path.GetDirectoryName(log_file);
			string log_1 = Path.Combine(path, file + "_1" + extension);
			string log_2 = Path.Combine(path, file + "_2" + extension);
			
			LogFile_1 = new FileInfo(log_1);
			LogFile_2 = new FileInfo(log_2);
			
			this.GetCurrentLogFile();
			this.CreateLogFileDirectory();
			
			this.ConsoleOutput = Console.Out;
			this.OpenFileStream(true);
			
			LogWriter.Current = this;
		}
		
		private void OpenFileStream(bool add_header)
		{
            lock (this)
            {
                try
                {
                    this.FileOutput = new StreamWriter(this.CurrentLogFile.FullName, true, Encoding.UTF8);
                    this.FileOutput.AutoFlush = true;
                    if (add_header == true)
                    {
                        this.FileOutput.WriteLine("\n\n\n\n");
                        this.FileOutput.WriteLine("==========================================================================");
                        this.FileOutput.WriteLine("Application start-up: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        this.FileOutput.WriteLine("==========================================================================");
                    }
                    this.FileStreamIsOpen = true;
                }
                catch (Exception)
                {
                    this.FileStreamIsOpen = false;
                }
            }
		}
		
		private void CloseFileStream()
		{
            lock (this)
            {
                try
                {
                    this.FileOutput.Close();
                    this.FileStreamIsOpen = false;
                }
                catch (Exception)
                {
                    this.FileStreamIsOpen = false;
                }
            }
		}
		
		public void ZipLogFiles(string archive_name, bool over_write)
		{
			this.CloseFileStream();
			List<FileInfo> files = new List<FileInfo>();
            this.LogFile_1.Refresh();
			if (this.LogFile_1.Exists == true)
				files.Add(this.LogFile_1);
			
            this.LogFile_2.Refresh();
			if (this.LogFile_2.Exists == true)	
				files.Add(this.LogFile_2);

			Zip zip = new Zip(archive_name,over_write);
			zip.Add(files);
			zip.Finish();
			this.OpenFileStream(false);
		}
		
		private void GetCurrentLogFile()
		{
			if (this.LogFile_1.Exists == false)
			{
				this.CurrentLogFile = this.LogFile_1;
				return;
			}
			if (this.LogFile_1.Exists == true)
			{
				double size = this.LogFile_1.Length / 1024.0 / 1024.0;
				if (size < this.MaxSize)
				{
					this.CurrentLogFile = this.LogFile_1;
					return;
				}
			}
			
			if (this.LogFile_2.Exists == false)
			{
				this.CurrentLogFile = this.LogFile_2;
				return;
			}
			
			if (this.LogFile_2.Exists == true)
			{
				double size = this.LogFile_2.Length / 1024.0 / 1024.0;
				if (size < this.MaxSize)
				{
					this.CurrentLogFile = this.LogFile_2;
					return;
				}
			}
			
			if (this.LogFile_1.Exists == true && this.LogFile_2.Exists == true)
			{
				if (this.LogFile_1.LastWriteTime < this.LogFile_2.LastWriteTime)
				{
					this.LogFile_1.Delete();
					this.CurrentLogFile = this.LogFile_1;
				}
				else
				{
					this.LogFile_2.Delete();
					this.CurrentLogFile = this.LogFile_2;
				}
			}
			
		}
		
		private void CreateLogFileDirectory()
		{
			if (this.CurrentLogFile.Exists == false)
			{
				if (this.CurrentLogFile.Directory.Exists == false)
					Directory.CreateDirectory(this.CurrentLogFile.DirectoryName);
			}
		}

		public override string ToString ()
		{
			return this.CurrentLogFile.FullName;
		}
	
		private FileInfo LogFile_1			{get; set;}
		private FileInfo LogFile_2			{get; set;}
				
		private FileInfo CurrentLogFile		{get; set;}
		private double MaxSize				{get; set;}
		
		private TextWriter ConsoleOutput 	{get; set;}
		private StreamWriter FileOutput 	{get; set;}
		private bool FileStreamIsOpen		{get; set;}
	

		#region IDisposable implementation
		public new void Dispose ()
		{
			try
			{
				this.CloseFileStream();
			}
			catch(Exception)
			{
			}
			base.Dispose();
		}
		#endregion

	}
}

