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

namespace BlackBoxFile
{
    /// <summary>
    /// 黑匣子
    /// </summary>
    public class CBlackBoxFile
    {
        private static readonly int FILE_LENGTH = 1024 * 100;//100K
        private static readonly int FILE_BACK_LENGTH = 1024 * 1024;//1M,可以根据实际情况调整
        private static readonly int MAX_NUMBER_FILE = 3;//备份文件的个数+1，为4
        //private static readonly string strDir = System.IO.Directory.GetCurrentDirectory() + "\\MyFile";
        //private static readonly string strBakDir = System.IO.Directory.GetCurrentDirectory() + "\\MyBakFile";
        private static readonly string strDir =  "C:\\MyFile";
        private static readonly string strBakDir = "C:\\MyBakFile";
        private List<string> mFileList = new List<string>();
        private static Mutex m_MutexSection = new Mutex();

        internal CBlackBoxFile()
        {

        }
        /// <summary>
        /// 黑匣子记录的入口
        /// </summary>
        /// <param name="uFileName">文件的编号</param>
        /// <param name="fileContext">要记录的信息</param>
        public void WriteFile(ushort uFileName, string fileContext)
        {
            fileContext = DateTime.Now.ToString() + ": " + fileContext;
            DirectoryInfo dir = new DirectoryInfo(strDir);
            if (!dir.Exists)
            {
                CreateDir(strDir);
            }
            string strFileName = uFileName + ".txt";
            string fname = strDir + "\\" + strFileName;
            FileInfo finfo = new FileInfo(fname);
            if (finfo.Exists && finfo.Length > FILE_LENGTH)
            {
                //备份文件
                m_MutexSection.WaitOne();
                DirectoryInfo dirBak = new DirectoryInfo(strBakDir);
                if (!dirBak.Exists)
                {
                    CreateDir(strBakDir);
                }
                //删除该文件 
                try
                {
                    //做备份处理
#if TEST
#else
                    string strText = File.ReadAllText(fname);
                    strText += fileContext;//带上该帧数据
                    DelBakFile(MAX_NUMBER_FILE, uFileName, strText);
#endif
                    File.WriteAllText(fname, "");
                }
                catch (Exception ex)
                {
                    Console.Write(ex.ToString());
                }
                m_MutexSection.ReleaseMutex();
                //判断备份件个数是否大于N，大于删除最先一个，再备份
            }
            else
            {
                try
                {
                    //如果不存在，创建文件，并写内容
                    if (!finfo.Exists)
                    {
                        CreateMyFile(uFileName, fileContext);
                    }
                    //否则的话，追加
                    else
                    {
                        AppendMyText(uFileName, fileContext);
                    }
                }
                catch (Exception ex)
                {
                    Console.Write(ex.ToString());
                }
            }
        }

        //创建文件
        /// <summary>
        /// 创建新的文件
        /// </summary>
        /// <param name="uFileName">文件编号</param>
        /// <param name="fileContext">要记录的信息</param>
        private void CreateMyFile(ushort uFileName, string fileContext)
        {
            m_MutexSection.WaitOne();
            FileInfo fi = new FileInfo(strDir + "\\" + uFileName + ".txt");
            //写操作
            StreamWriter w = fi.CreateText();
            w.WriteLine(fileContext);
            w.Close();
            m_MutexSection.ReleaseMutex();

        }
        /// <summary>
        /// 追加信息
        /// </summary>
        /// <param name="uFileName">文件的编号</param>
        /// <param name="fileContext">要记录的信息</param>
        private void AppendMyText(ushort uFileName, string fileContext)
        {
            m_MutexSection.WaitOne();
            try
            {
                FileInfo fi = new FileInfo(strDir + "\\" + uFileName + ".txt");
                StreamWriter w = fi.AppendText();
                w.WriteLine(fileContext);
                w.Close();
            }
            catch (Exception ex)
            {
                Console.Write(ex.ToString());
            }
            m_MutexSection.ReleaseMutex();
        }

        /// <summary>
        /// 获取系统时间
        /// </summary>
        /// <returns>返回系统时间的编码</returns>
        private string GetSysTime()
        {
            string timeFileName = "";
            timeFileName = DateTime.Now.Year.ToString();
            if (int.Parse(DateTime.Now.Month.ToString()) < 10)
            {
                timeFileName += "0" + DateTime.Now.Month.ToString();
            }
            else
            {
                timeFileName += DateTime.Now.Month.ToString();
            }

            if (int.Parse(DateTime.Now.Day.ToString()) < 10)
            {
                timeFileName += "0" + DateTime.Now.Day.ToString();
            }
            else
            {
                timeFileName += DateTime.Now.Day.ToString();
            }

            if (int.Parse(DateTime.Now.Hour.ToString()) < 10)
            {
                timeFileName += "0" + DateTime.Now.Hour.ToString();
            }
            else
            {
                timeFileName += DateTime.Now.Hour.ToString();
            }

            if (int.Parse(DateTime.Now.Minute.ToString()) < 10)
            {
                timeFileName += "0" + DateTime.Now.Minute.ToString();
            }
            else
            {
                timeFileName += DateTime.Now.Minute.ToString();
            }
            if (int.Parse(DateTime.Now.Second.ToString()) < 10)
            {
                timeFileName += "0" + DateTime.Now.Second.ToString();
            }
            else
            {
                timeFileName += DateTime.Now.Second.ToString();
            }

            return timeFileName;


        }

        //创建目录
        private void CreateDir(string directory)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(directory);
            dirInfo.Create();
        }

        //判断备份文件个数是否大于N，大于删除最先一个，再备份
        private void DelBakFile(int n, ushort ID, string strText)
        {
            mFileList.Clear();

            string strPathFile = strBakDir + "\\";
            int bakFileNum = GetBakFileNum(ID);

            mFileList.Sort();

            if (bakFileNum > n)
            {
                string strMax = strPathFile + mFileList[bakFileNum - 1];

                FileInfo finfo = new FileInfo(strMax);

                if (finfo.Length > FILE_BACK_LENGTH)
                {
                    strPathFile += mFileList[0];

                    FileInfo firBakFile = new FileInfo(strPathFile);

                    firBakFile.Delete();

                    DelBakFile(n, ID, strText);
                }
                else
                {
                    strPathFile += mFileList[bakFileNum - 1];

                    File.AppendAllText(strPathFile, strText);
                }
            }
            else if (bakFileNum == 0)
            {

                string bakName = strBakDir + "\\";

                bakName += GetSysTime();
                bakName += "_" + ID;
                bakName += "_";
                bakName += ".txt";

                FileInfo fi = new FileInfo(bakName);
                //写操作
                StreamWriter w = fi.CreateText();

                w.Write(strText);

                w.Close();


            }
            else if (bakFileNum > 0 && bakFileNum <= n)
            {
                string strMax = strPathFile + mFileList[bakFileNum - 1];

                FileInfo finfo = new FileInfo(strMax);

                if (finfo.Length > FILE_BACK_LENGTH)
                {
                    string bakName = strBakDir + "\\";

                    bakName += GetSysTime();

                    bakName += "_" + ID;
                    bakName += "_";
                    bakName += ".txt";

                    FileInfo firBakFile = new FileInfo(bakName);

                    StreamWriter w = firBakFile.CreateText();

                    w.Write(strText);

                    w.Close();
                }
                else
                {
                    File.AppendAllText(strMax, strText);
                }
            }
        }

        //获得备份文件个数
        private int GetBakFileNum(ushort ID)
        {
            int n = 0;
            DirectoryInfo dirInfo = new DirectoryInfo(strBakDir);
            string str = "_" + ID.ToString() + "_";
            foreach (FileSystemInfo fsi in dirInfo.GetFileSystemInfos())
            {
                if (fsi is FileInfo && fsi.Extension == ".txt")
                {
                    if (fsi.Name.Contains(str))
                    {
                        mFileList.Add(fsi.Name);
                        n++;
                    }
                }
            }
            return n;
        }
    }
}

