using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

using ITC81DB_0H.Forms;

namespace ITC81DB_0H
{
    public class VersionIniFile
    {
        [DllImport("KERNEL32.DLL")]
        private static extern bool WritePrivateProfileString(string IpAppName, string IpKeyName, string IpString, string IpFileName);

        [DllImport("KERNEL32.DLL")]
        private static extern uint GetPrivateProfileInt(string IpAppName, string IpKeyName, int nDefault, string IpFileName);

        [DllImport("KERNEL32.DLL")]
        static extern uint GetPrivateProfileString(string IpAppName, string IpKeyName, string IpDefault, StringBuilder IpReturnedString, int nSize, string IpFileName);

        /// <summary>
        /// Ini 파일 읽기
        /// </summary>
        /// <param name="IpAppName">값을 가져올 키가 속해있는 [섹션] 문자열</param>
        /// <param name="IpKeyName">값을 가져올 키</param>
        /// <param name="IpDefault">해당되는 값이 없을 경우, 기본값으로 리턴할 문자열</param>
        /// <param name="filePath">읽어올 ini 파일 경로</param>
        /// <returns>실패 : "" 반환</returns>
        public static string GetIni(String IpAppName, string IpKeyName, string IpDefault, string filePath)
        {
            string ret = "";
            string iniFile = filePath;

            try
            {
                string readString = "";
                string[] stringArray;

                using (StreamReader sr = new StreamReader(filePath, Encoding.Default))
                {
                    readString = sr.ReadToEnd();
                    sr.BaseStream.Position = 0;

                    // Key값이 포함된 Line을 읽을 경우
                    if (readString.Contains(IpKeyName) == true)
                    {
                        int length;
                        string[] text = readString.Split('\n');
                        for (int i = 0; i < text.Length; i++)
                            text[i] = text[i].Trim();

                        for (int i = 0; i < text.Length; i++)
                        {
                            if (text[i].StartsWith(IpKeyName) == true)
                            {
                                stringArray = text[i].Split('=');
                                ret = stringArray[stringArray.Length - 1];

                                break;
                            }
                        }
                        sr.Close();
                    }
                }

                return ret;
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        /// <summary>
        /// Ini 파일 쓰기
        /// </summary>
        /// <param name="IpAppName">값을 입력할 키가 속해있는 [섹션] 문자열</param>
        /// <param name="IpKeyName">값을 입력할 키</param>
        /// <param name="IpValue">쓸 키 값</param>
        /// <param name="filePath">쓸 ini 파일 경로</param>
        /// <returns>성공 : true, 실패 : false</returns>
        public static Boolean SetIni(string IpAppName, string IpKeyName, string IpValue, string filePath)
        {
            try
            {
                string iniFile = filePath;
                string readString = "";

                using (StreamReader sr = new StreamReader(filePath, Encoding.Default))
                {
                    readString = sr.ReadToEnd();
                    sr.BaseStream.Position = 0;

                    // Key값이 포함된 Line을 읽을 경우
                    if (readString.Contains(IpKeyName) == true)
                    {
                        int length;
                        string[] text = readString.Split('\n');
                        for (int i = 0; i < text.Length; i++)
                            text[i] = text[i].Trim();

                        for (int i = 0; i < text.Length; i++)
                        {
                            if (text[i].StartsWith(IpKeyName) == true)
                            {
                                length = text[i].Length;

                                int offset = readString.IndexOf(IpKeyName, 0);
                                readString = readString.Remove(offset, length);
                                readString = readString.Insert(offset, IpKeyName + "=" + IpValue);

                                break;
                            }
                        }

                        sr.Close();

                        File.Delete(filePath);

                        StreamWriter sw = new StreamWriter(filePath, true, Encoding.Default);

                        sw.Write(readString);
                        sw.Close();

                        return true;
                    }
                }          

                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Ini 파일 생성
        /// </summary>
        /// <param name="programName">Program명(ex. ITC81DB)</param>
        /// <param name="version">Version(ex. 8.0.0)</param>
        /// <param name="releaseDate">릴리즈 날짜(ex. 2022.03.04)</param>
        /// <returns>성공 : true, 실패 : false</returns>
        public static Boolean CreateVersionIni(string programName, string version, string releaseDate)
        {
            try
            {
                string strCheckFolder = "";

                strCheckFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\";
                strCheckFolder += "Version.ini";
                if (File.Exists(strCheckFolder) == false)
                {
                    using (StreamWriter sw = new StreamWriter(strCheckFolder, true, Encoding.Default))
                    {
                        sw.Write("[PROGRAMINFO]" + "\r\n");
                        sw.Write("NAME=" + programName + "\r\n");
                        sw.Write("VERSION=" + version + "\r\n");
                        sw.Write("RELEASE=" + releaseDate + "\r\n");
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }
    }

    public class LogIniFile
    {
        /*
         * Checkmate / 2010.08
         * IniFile 클래스는 Ini를 읽고 쓸 수 있도록 구현한 것이다.
         * 동일한 함수명을 가진 static함수와 일반함수로 나누어져 있다.
         * 
         * 한 두 번만 사용할 경우에는 인스턴스 생성 없이 static함수를 이용하여 사용하면 된다. 
         * 개체의 생성 소멸이 필요 없다.
         * 매번 지정된 파일을 찾아야 한다.
         *
         * 동일한 파일에 여러번 사용할 경우에는 인스턴스를 생성하여 사용하는 것이 좋다. 
         * 내부적으로 FileInfo개체를 생성하여 파일을 검색하는 시간을 절약하도록 구현됐다.
         * 따라서 생성 시에 파일이름을 전달하여야 한다. IniFile ini = new IniFile("C:\\Temp\\Test.ini");
         * 
         * ReadString() : ini에서 문자열 값을 읽어 온다.
         * ReadInteger() : ini에서 정수(int32) 값을 읽어 온다.
         * ReadBool() : ini에서 bool 값을 읽어 온다.
         * 
         * WriteString() : ini에 문자열 값을 쓴다.
         * WriteInteger() : ini에 정수(int32) 값을 쓴다.
         * WriteBool() : ini에 bool 값을 쓴다.
         */

        #region Field
        FileInfo fi;
        #endregion

        #region Constructor
        public LogIniFile(String filename)
        {
            //파일 검색 과정을 줄이기 위해 파일정보를 클래스 생성 시 파일 정보를 설정한다.
            fi = new FileInfo(filename);
        }
        #endregion

        #region Method
        public int ReadInteger(String sSect, String sKey, int defaultvalue)
        {
            String sValue;
            sValue = defaultvalue.ToString();
            sValue = ReadString(sSect, sKey, sValue);
            return Convert.ToInt32(sValue);
        }
        public bool ReadBool(String sSect, String sKey, bool defaultvalue)
        {
            String sValue;
            if (defaultvalue == true)
            {
                sValue = "1";
            }
            else
            {
                sValue = "0";
            }
            sValue = ReadString(sSect, sKey, sValue);

            if (sValue == "1")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public String ReadString(String sSect, String sKey, String defaultvalue)
        {
            if (fi.Exists == false)
            {
                return defaultvalue;
            }
            String result = defaultvalue;
            String strLine;

            String[] strArr;
            char[] tokenArr = new char[] { '=' };

            bool bFindSect = false;
            int nOffset1;
            int nOffset2;

            FileStream fs = fi.OpenRead();
            StreamReader sr = new StreamReader(fs);
            sSect = "[" + sSect.ToUpper() + "]";
            sKey = sKey.ToUpper();

            strLine = sr.ReadLine();

            while (strLine != null)
            {
                nOffset1 = strLine.IndexOf(']');
                if (strLine == "") //빈라인은 처리
                {
                    //
                }
                else if ((strLine[0] == '[') && (nOffset1 > 1)) //해당 라인이 섹션이름인가
                {

                    if (bFindSect == true)
                    {
                        //섹션을 찾았다가 변경 되었으므로 진행 종료. //섹션은 동일한 것이 여러번 나타날 수 없다.
                        break;
                    }
                    else
                    {
                        if (strLine.ToUpper() == sSect) //Section Name 찾기
                        {
                            //섹션이름을 찾았음
                            bFindSect = true;
                        }
                    }
                }
                else
                {
                    if (bFindSect)
                    {
                        //현재 섹션에서 진행중
                        nOffset2 = strLine.IndexOf('=');
                        if (nOffset2 > 0)
                        {
                            //key 영역
                            strArr = strLine.Split(tokenArr);
                            if (strArr.GetUpperBound(0) > 0)
                            {
                                if (strArr[0].ToUpper() == sKey)
                                {
                                    //KeyName 일치 - Found
                                    //값에 '='가 있을 수 있으므로 반복처리
                                    result = "";
                                    for (int i = 1; i <= strArr.GetUpperBound(0); i++)
                                    {
                                        result += strArr[i];
                                    }
                                    break;
                                }
                            } //if (strArr.GetUpperBound(0) == 1)

                        } //if (nOffset2 > 0)
                    } //if (bFindSect)
                } //else

                strLine = sr.ReadLine();
            } //while

            sr.Close();
            fs.Close();
            fi.Refresh();
            return result;
        }
        public bool WriteString(String sSect, String sKey, String sValue)
        {
            bool result = false;
            String strLine;
            String sectname;
            String keyname;
            String[] strArr;
            char[] tokenArr = new char[] { '=' };

            bool bFindSect = false;
            bool bFindKey = false;
            int nOffset1;
            int nOffset2;

            FileStream fs;
            FileStream fs2;
            StreamReader sr;
            StreamWriter sw;

            String sTempFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\IniTemp.ini";

            if (fi.Exists == false)
            {
                //파일이 없을 경우 
                fs2 = new FileStream(fi.FullName, FileMode.OpenOrCreate);
                sw = new StreamWriter(fs2);

                sw.WriteLine("[" + sSect + "]");
                sw.WriteLine("{0}={1}", sKey, sValue);
                sw.Close();

                fs2.Close();
                fi.Refresh(); //정보를 갱신해야 다음에 Exists가 처리된다.

                return true;
            }

            fs = fi.OpenRead();
            fs2 = new FileStream(sTempFile, FileMode.OpenOrCreate);

            sr = new StreamReader(fs);
            sw = new StreamWriter(fs2);

            sectname = "[" + sSect.ToUpper() + "]";
            keyname = sKey.ToUpper();

            strLine = sr.ReadLine();

            while (strLine != null)
            {
                nOffset1 = strLine.IndexOf(']');
                if (strLine == "") //빈라인은 처리
                {
                    sw.WriteLine("");
                }
                else if ((strLine[0] == '[') && (nOffset1 > 1)) //해당 라인이 섹션이름인가
                {

                    if (bFindSect == true)
                    {
                        //섹션을 찾았다가 변경 되었음 //섹션은 동일한 것이 여러번 나타날 수 없다.
                        if (bFindKey == false)
                        {
                            //해당키 찾지 못함 //키 추가
                            sw.WriteLine("{0}={1}", sKey, sValue);
                            result = true;
                            bFindKey = true;
                        }
                        sw.WriteLine(strLine);
                    }
                    else
                    {
                        if (strLine.ToUpper() == sectname) //Section Name 찾기
                        {
                            //섹션이름을 찾았음
                            bFindSect = true;
                        }
                        sw.WriteLine(strLine);
                    }

                }
                else
                {
                    if (bFindSect)
                    {
                        //현재 섹션에서 진행중
                        nOffset2 = strLine.IndexOf('=');
                        if (bFindKey)
                        {
                            //키값을 이미 처리되었음 //그냥 복사만
                            sw.WriteLine(strLine);
                        }
                        else if (nOffset2 > 0)
                        {
                            //key 영역
                            strArr = strLine.Split(tokenArr);
                            if (strArr.GetUpperBound(0) > 0)
                            {
                                if (strArr[0].ToUpper() == keyname)
                                {
                                    //KeyName 일치 - Found
                                    sw.WriteLine("{0}={1}", strArr[0], sValue); //기존 키이름 보존
                                    result = true;
                                    bFindKey = true;
                                }
                                else
                                {
                                    sw.WriteLine(strLine);
                                }
                            } //if (strArr.GetUpperBound(0) == 1)
                            else
                            {
                                sw.WriteLine(strLine);
                            }

                        } //if (nOffset2 > 0)
                    } //if (bFindSect)
                    else
                    {
                        sw.WriteLine(strLine);
                    }
                } //else

                strLine = sr.ReadLine();
            } //while

            //키를 찾지 못했으면 새로이 추가
            if (bFindKey == false)
            {
                if (bFindSect == false) //섹션도 못 찾았을 경우 추가
                {
                    sw.WriteLine("[" + sSect + "]");
                }
                sw.WriteLine("{0}={1}", sKey, sValue);
                result = true;
            }

            sr.Close();
            fs.Close();

            sw.Close();
            fs2.Close();

            File.Copy(sTempFile, fi.FullName, true); //원본 파일에 임시파일 덮어쓰기
            File.Delete(sTempFile); //임시 파일 삭제
            fi.Refresh(); //정보를 갱신해야 다음에 Exists가 처리된다.
            return result;
        }
        public bool WriteInteger(String sSect, String sKey, int value)
        {
            String sValue;
            sValue = value.ToString();
            return WriteString(sSect, sKey, sValue);
        }
        public bool WriteBool(String sSect, String sKey, bool value)
        {
            String sValue;
            if (value == true)
            {
                sValue = "1";
            }
            else
            {
                sValue = "0";
            }
            return WriteString(sSect, sKey, sValue);
        }

        //static 함수
        public static int ReadInteger(String sFile, String sSect, String sKey, int defaultvalue)
        {
            String sValue;
            int nValue;
            sValue = defaultvalue.ToString();
            sValue = ReadString(sFile, sSect, sKey, sValue);
            try
            {
                nValue = Convert.ToInt32(sValue);
                return nValue;
            }
            //catch (System.Exception e)
            catch
            {
                return defaultvalue;
            }
        }
        public static bool ReadBool(String sFile, String sSect, String sKey, bool defaultvalue)
        {
            String sValue;
            if (defaultvalue == true)
            {
                sValue = "1";
            }
            else
            {
                sValue = "0";
            }
            sValue = ReadString(sFile, sSect, sKey, sValue);

            if (sValue == "1")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static String ReadString(String sFile, String sSect, String sKey, String defaultvalue)
        {
            if (File.Exists(sFile) == false)
            {
                return defaultvalue;
            }

            String result = defaultvalue;
            String strLine;

            String[] strArr;
            char[] tokenArr = new char[] { '=' };

            bool bFindSect = false;
            int nOffset1;
            int nOffset2;

            FileStream fs = new FileStream(sFile, FileMode.OpenOrCreate);
            StreamReader sr = new StreamReader(fs);
            sSect = "[" + sSect.ToUpper() + "]";
            sKey = sKey.ToUpper();

            strLine = sr.ReadLine();

            while (strLine != null)
            {
                nOffset1 = strLine.IndexOf(']');
                if (strLine == "") //빈라인은 처리
                {
                    //
                }
                else if ((strLine[0] == '[') && (nOffset1 > 1)) //해당 라인이 섹션이름인가
                {

                    if (bFindSect == true)
                    {
                        //섹션을 찾았다가 변경 되었으므로 진행 종료. //섹션은 동일한 것이 여러번 나타날 수 없다.
                        break;
                    }
                    else
                    {
                        if (strLine.ToUpper() == sSect) //Section Name 찾기
                        {
                            //섹션이름을 찾았음
                            bFindSect = true;
                        }
                    }
                }
                else
                {
                    if (bFindSect)
                    {
                        //현재 섹션에서 진행중
                        nOffset2 = strLine.IndexOf('=');
                        if (nOffset2 > 0)
                        {
                            //key 영역
                            strArr = strLine.Split(tokenArr);
                            if (strArr.GetUpperBound(0) > 0)
                            {
                                if (strArr[0].ToUpper() == sKey)
                                {
                                    //KeyName 일치 - Found
                                    //값에 '='가 있을 수 있으므로 반복처리
                                    result = "";
                                    for (int i = 1; i <= strArr.GetUpperBound(0); i++)
                                    {
                                        result += strArr[i];
                                    }
                                    break;
                                }
                            } //if (strArr.GetUpperBound(0) == 1)

                        } //if (nOffset2 > 0)
                    } //if (bFindSect)
                } //else

                strLine = sr.ReadLine();
            } //while

            sr.Close();
            fs.Close();
            return result;
        }
        public static bool WriteString(String sFile, String sSect, String sKey, String sValue)
        {
            bool result = false;
            String strLine;
            String sectname;
            String keyname;
            String[] strArr;
            char[] tokenArr = new char[] { '=' };

            bool bFindSect = false;
            bool bFindKey = false;
            int nOffset1;
            int nOffset2;

            String sTempFile = string.Format("{0}{1}", FormMain.PathBinFolder, "IniTemp.ini");

            FileStream fs = new FileStream(sFile, FileMode.OpenOrCreate);
            FileStream fs2 = new FileStream(sTempFile, FileMode.OpenOrCreate);

            StreamReader sr = new StreamReader(fs);
            StreamWriter sw = new StreamWriter(fs2);

            sectname = "[" + sSect.ToUpper() + "]";
            keyname = sKey.ToUpper();

            strLine = sr.ReadLine();

            while (strLine != null)
            {
                nOffset1 = strLine.IndexOf(']');
                if (strLine == "") //빈라인은 처리
                {
                    sw.WriteLine("");
                }
                else if ((strLine[0] == '[') && (nOffset1 > 1)) //해당 라인이 섹션이름인가
                {

                    if (bFindSect == true)
                    {
                        //섹션을 찾았다가 변경 되었음 //섹션은 동일한 것이 여러번 나타날 수 없다.
                        if (bFindKey == false)
                        {
                            //해당키 찾지 못함 //키 추가
                            sw.WriteLine("{0}={1}", sKey, sValue);
                            result = true;
                            bFindKey = true;
                        }
                        sw.WriteLine(strLine);
                    }
                    else
                    {
                        if (strLine.ToUpper() == sectname) //Section Name 찾기
                        {
                            //섹션이름을 찾았음
                            bFindSect = true;
                        }
                        sw.WriteLine(strLine);
                    }

                }
                else
                {
                    if (bFindSect)
                    {
                        //현재 섹션에서 진행중
                        nOffset2 = strLine.IndexOf('=');
                        if (bFindKey)
                        {
                            //키값을 이미 처리되었음 //그냥 복사만
                            sw.WriteLine(strLine);
                        }
                        else if (nOffset2 > 0)
                        {
                            //key 영역
                            strArr = strLine.Split(tokenArr);
                            if (strArr.GetUpperBound(0) > 0)
                            {
                                if (strArr[0].ToUpper() == keyname)
                                {
                                    //KeyName 일치 - Found
                                    sw.WriteLine("{0}={1}", strArr[0], sValue); //기존 키 이름 보존
                                    result = true;
                                    bFindKey = true;
                                }
                                else
                                {
                                    sw.WriteLine(strLine);
                                }
                            } //if (strArr.GetUpperBound(0) == 1)
                            else
                            {
                                sw.WriteLine(strLine);
                            }

                        } //if (nOffset2 > 0)
                    } //if (bFindSect)
                    else
                    {
                        sw.WriteLine(strLine);
                    }
                } //else

                strLine = sr.ReadLine();
            } //while

            //키를 찾지 못했으면 새로이 추가
            if (bFindKey == false)
            {
                if (bFindSect == false) //섹션도 못 찾았을 경우 추가
                {
                    sw.WriteLine("[" + sSect + "]");
                }
                sw.WriteLine("{0}={1}", sKey, sValue);
                result = true;
            }

            sr.Close();
            fs.Close();

            sw.Close();
            fs2.Close();

            File.Copy(sTempFile, sFile, true);
            File.Delete(sTempFile);

            return result;
        }
        public static bool WriteInteger(String sFile, String sSect, String sKey, int value)
        {
            String sValue;
            sValue = value.ToString();
            return WriteString(sFile, sSect, sKey, sValue);
        }
        public static bool WriteBool(String sFile, String sSect, String sKey, bool value)
        {
            String sValue;
            if (value == true)
            {
                sValue = "1";
            }
            else
            {
                sValue = "0";
            }
            return WriteString(sFile, sSect, sKey, sValue);
        }
        #endregion
    }
}