using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AR;

namespace Project.Manager
{
    public class DatabaseManager
    {
        /// <summary>
        /// 파일검색방법
        /// </summary>
        public enum eFileSearchMode
        {
            Normal,
            Project,
            Model,
            MCCode,
            Barcode,
            All,
        }

        public enum eStripSearchResult
        {
            None,
            OK,
            NG,
        }

        /// <summary>
        /// 버퍼갯수(지정 갯수가 차면 실제파일에 기록을 한다)
        /// </summary>
        private int MaxBufferCount = 1;

        /// <summary>
        /// 최종파일
        /// </summary>
        private String LastFileName;


        private string[] dataPath = new string[] { };
        private DataSet1.ResultDataDataTable dt;
       // private string _subDirName = string.Empty;

        /// <summary>
        /// 파일디비초기화작업(클라이언트 갯수만큼 버퍼를 확보한다)
        /// </summary>
        public DatabaseManager(string[] dataPath_, int _MaxBufferCount = 100)
        {
            LastFileName = string.Empty;
            dt = new DataSet1.ResultDataDataTable();

            this.dataPath = dataPath_;
            if (dataPath_.Length == 0) dataPath = new string[]{ System.IO.Path.Combine(UTIL.CurrentPath, "Data")};

            //최대버퍼갯수(이 갯수를 넘어가면 실제 파일에 기록한다)
            MaxBufferCount = _MaxBufferCount;
            //_subDirName = subDirName;
        }

        //해당 결과를 버퍼에 추가한다.
        public void Add(DataSet1.ResultDataRow dataRow, Boolean autoFlush = false)
        {
            //입력된 자료를 복사해서 버퍼에 넣는다.
            var newdr = this.dt.NewResultDataRow();
            foreach (string col in getDataColumnList())
            {
                newdr[col] = dataRow[col];
            }
            this.dt.AddResultDataRow(newdr);

            //만약자료가 일정데이터수를 넘었다면 flush 한다
            if (autoFlush || dt.Rows.Count >= MaxBufferCount)
            {
                Flush();  //파일에 실제저장한다.                
            }
        }

        /// <summary>
        /// 신규파일을 생성합니다.
        /// </summary>
        /// <param name="filename"></param>
        void MakeFile(string filename)
        {
            //파일이없다면 헤더를 만들어준다.
            AR.XMLHelper xml = new AR.XMLHelper(filename);
            xml.CreateFile();
        }

        /// <summary>
        /// 저장해야할 컬럼명을 반환한다.(idx는 제외한다)
        /// </summary>
        /// <returns></returns>
        public string[] getDataColumnList()
        {
            //저장하고자하는 순서를 미리 지정한다.(지정안된 자료는 알아서 저장된다)
            string[] reserveCols = new string[] { };
            List<String> cols = new List<string>();
            cols.AddRange(reserveCols);

            for (int i = 0; i < this.dt.Columns.Count; i++)
            {
                string colname = dt.Columns[i].ColumnName;
                if (reserveCols.Contains(colname)) continue;
                cols.Add(colname);
            }
            return cols.ToArray();
        }

        public void Flush()
        {
            //데이터가없다면 처리하지 않음            
            if (this.dt.Rows.Count < 1) return;

            //쓸데이터를 모두 버퍼에 밀어넣는다.

            foreach (DataSet1.ResultDataRow dr in dt.Rows)
            {
                if (dr.RowState == System.Data.DataRowState.Deleted || dr.RowState == System.Data.DataRowState.Detached) continue;

                //lot date check
                if (dr.time_start.Year == 1982) dr.time_start = DateTime.Now;
                if (dr.time_end.Year == 1982) dr.time_end = DateTime.Now;

                //작업이 종료된 시간을 기준으로 파일을 생성한다.
                // if (dr.info_lot.isEmpty()) dr.info_lot = "NoLot";
                //if (dr.info_stripid.isEmpty()) dr.info_stripid = "S" + dr.time_pcbstart.ToString("yyyyMMddHHmmss");

                //string curdatestr = string.Format("{0:0000}\\{1:00}\\{2:00}\\{3}\\{4}",
                //  dr.time_lotstart.Year, dr.time_lotstart.Month, dr.time_lotstart.Day, dr.info_lot,dr.info_stripid);

                //저장할 파일 체크
                System.IO.FileInfo fi =new System.IO.FileInfo(  dr.info_filename+".xml");

                //폴더새엇ㅇ
                if (!fi.Directory.Exists) fi.Directory.Create();

                //파일없는경우 헤더생성
                if (!fi.Exists) MakeFile(fi.FullName);

                //파일에기록
                try
                {
                    //general info
                    var xml = new AR.XMLHelper(fi.FullName);
                    foreach(System.Data.DataColumn dc in this.dt.Columns)
                    {
                        if (dc.ColumnName.ToLower() == "idx") continue;
                        if (dc.ColumnName.ToLower() == "filename") continue;
                        var colname = dc.ColumnName.Split('_');
                        var data = dr[dc.ColumnName];
                        if(colname[0].ToLower()=="time")
                        {
                            string date_value = "";
                            if (data != null && data != DBNull.Value)
                                date_value = ((DateTime)data).ToString("yyyy-MM-dd HH:mm:ss");
                            xml.set_Data(colname[0], colname[1], date_value);
                                
                        } else
                        {
                            if(data != null && data != DBNull.Value)
                                xml.set_Data(colname[0], colname[1], data.ToString());
                            else
                                xml.set_Data(colname[0], colname[1], "");
                        }
                    }
                    string savemsg;
                    xml.Save(out savemsg);
                }
                catch (Exception ex)
                {
                    PUB.log.AddE("DBMAN:FLUSH:" + ex.Message);
                    return;
                }

                PUB.log.Add("DATABASE", string.Format("◆ Data Saved : {0}", fi.Name));
            }

            dt.Clear();
            dt.AcceptChanges();
        }

        /// <summary>
        /// 지정된 파일의 모든 내용을 읽어서 DataTable 로 반환합니다.
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public DataSet1.ResultDataDataTable GetDatas(List<System.IO.FileInfo> files)
        {
            DataSet1.ResultDataDataTable retval = new DataSet1.ResultDataDataTable();
            //모든파일을 대상으로한다.

            foreach(var file in files)
            {
                var newdr = retval.NewResultDataRow();
                newdr.info_filename = file.FullName;
                var xml = new AR.XMLHelper(file.FullName);
                foreach (System.Data.DataColumn col in retval.Columns)
                {
                    if (col.ColumnName.ToLower() == "idx") continue;
                    if (col.ColumnName.ToLower() == "filename") continue;
                    var colbuf = col.ColumnName.Split('_');

                    var readstr = xml.get_Data(colbuf[0], colbuf[1]);
                    if(col.DataType == typeof(DateTime))
                    {
                        if(readstr != "")
                        {
                            DateTime dt;
                            if (DateTime.TryParse(readstr, out dt))
                                newdr[col.ColumnName] = dt;
                        }
                    }
                    else
                    {
                        newdr[col.ColumnName] =readstr;
                    }
                    
                    
                }
                retval.AddResultDataRow(newdr);
            }
            

            retval.AcceptChanges();
            return retval;
        }


        public eStripSearchResult FindStrip(List<String> pathlist, string strip)
        {
            //지정된 경로내에 스트립파일이 존재하는가?
            foreach(var path in pathlist)
            {
                var filese = System.IO.Directory.GetFiles( path , strip + ".xml");
                if(filese .Length == 1)
                {
                    var xml = new AR.XMLHelper(filese[0]);
                    var upload = xml.get_Data("info", "upload");
                    if (upload == "O") return eStripSearchResult.OK;
                }
            }
            return eStripSearchResult.None;
        }
        /// <summary>
        /// 지정된 파일의 모든 내용을 읽어서 DataTable 로 반환합니다.
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public eStripSearchResult FindStrip(List<System.IO.FileInfo> files, string strip)
        {
            eStripSearchResult retval = eStripSearchResult.None;
            System.Text.StringBuilder sbError = new StringBuilder();
            if (files.Count < 1) return eStripSearchResult.None;

            //가장최신의데이터를 찾아야한다.
            DateTime MaxDate = DateTime.Parse("1982-11-23");
            string MaxResult = string.Empty;

            foreach (var fi in files.OrderByDescending(t => t.FullName))
            {
                Boolean DataFind = false;
                List<String> cols = new List<string>();
                System.IO.FileStream fs = new System.IO.FileStream(fi.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
                System.IO.StreamReader sr = new System.IO.StreamReader(fs, System.Text.Encoding.ASCII);
                int LineCount = 0;
                while (sr.Peek() > 0)
                {
                    string buffer = sr.ReadLine();
                    LineCount += 1;
                    if (buffer.isEmpty() || buffer.StartsWith(";")) continue;
                    var databuffer = buffer.Split(',');
                    if (cols.Count < 1)
                    {
                        //줄로처리한다.
                        foreach (string colname in databuffer)
                            cols.Add(colname);
                    }
                    else
                    {
                        //지정한 바코드 자료만 처리한다.
                        if (databuffer[2] != strip) continue;

                        DateTime endtime;
                        if (DateTime.TryParse(databuffer[4], out endtime))
                        {
                            MaxResult = databuffer[5];
                            if (MaxResult.ToUpper() != "FAIL")
                            {
                                if (endtime > MaxDate)
                                {
                                    MaxDate = endtime;
                                    if (MaxResult == "OK")
                                        retval = eStripSearchResult.OK;
                                    else if (MaxResult == "NG")
                                        retval = eStripSearchResult.NG;
                                }
                                DataFind = true; //다른파일은 작동하지 않게한다.
                            }
                        }
                    }
                }

                sr.Close();
                sr.Dispose();
                fs.Close();
                fs.Dispose();
                if (DataFind) break;
            }
            return retval;
        }

        public List<String> GetPathListbyLot(DateTime sdate, DateTime edate, string lot)
        {
            List<String> retfiles = new List<String>();
            //날짜사이의 모든 파일을 대상으로해야함

            string sd = sdate.ToShortDateString();
            string ed = edate.ToShortDateString();

            int sy = sdate.Year;
            int ey = edate.Year;
            int sm = sdate.Month;
            int em = edate.Month;
            int sday = sdate.Day;
            int eday = edate.Day;

            Boolean endtast = false;
            for (int y = sy; y <= ey; y++)
            {
                for (int m = 1; m <= 12; m++)
                {
                    for (int d = 1; d <= 31; d++)
                    {
                        string daystr = string.Format("{0:0000}-{1:00}-{2:00}", y, m, d);
                        if (ed == daystr) endtast = true; //마지막 날짜이다.

                        if (y == sy && m < sm) continue; //시작년도 시작월 이전의 자료라면 넘어간다.
                        else if (y == sy && m == sm && d < sday) continue; //시작년도 시작월 시작일 이전의 자료라면 넘어간다.

                        foreach (var data in this.dataPath)
                        {
                            var path = new System.IO.DirectoryInfo(System.IO.Path.Combine(data, daystr.Replace("-", "\\"), lot));
                            if (path.Exists == false) continue;
                            else retfiles.Add(path.FullName);
                        }

                        if (endtast)
                            break; // TODO: might not be correct. Was : Exit For
                    }
                    if (endtast)
                        break; // TODO: might not be correct. Was : Exit For
                }
                if (endtast)
                    break; // TODO: might not be correct. Was : Exit For
            }
            return retfiles;
        }

        /// <summary>
        /// 지정된 기간사이의 파일명을 반환합니다.
        /// </summary>
        /// <param name="sdate">검색시작일(시간은 적용안함)</param>
        /// <param name="edate">검색종료일(시간은 적용안함)</param>
        /// <param name="extFilter">검색필터</param>
        /// <param name="SearchNo">장치번호</param>
        /// <param name="SearchBarcode">검색바코드</param>
        /// <returns></returns>
        public List<System.IO.FileInfo> Getfiles(DateTime sdate, DateTime edate)
        {
            List<System.IO.FileInfo> retfiles = new List<System.IO.FileInfo>();
            //날짜사이의 모든 파일을 대상으로해야함

            string sd = sdate.ToShortDateString();
            string ed = edate.ToShortDateString();

            int sy = sdate.Year;
            int ey = edate.Year;
            int sm = sdate.Month;
            int em = edate.Month;
            int sday = sdate.Day;
            int eday = edate.Day;
            
            Boolean endtast = false;
            for (int y = sy; y <= ey; y++)
            {
                for (int m = 1; m <= 12; m++)
                {
                    for (int d = 1; d <= 31; d++)
                    {
                        string daystr = string.Format("{0:0000}-{1:00}-{2:00}", y, m, d);
                        if (ed == daystr) endtast = true; //마지막 날짜이다.

                        if (y == sy && m < sm) continue; //시작년도 시작월 이전의 자료라면 넘어간다.
                        else if (y == sy && m == sm && d < sday) continue; //시작년도 시작월 시작일 이전의 자료라면 넘어간다.

                        foreach(var data in this.dataPath)
                        {
                            var path = new System.IO.DirectoryInfo(System.IO.Path.Combine(data, daystr.Replace("-", "\\")));
                            if (path.Exists == false) continue;
                            var files = path.GetFiles("*.xml", System.IO.SearchOption.AllDirectories);
                            if (files != null && files.Length > 0) retfiles.AddRange(files);
                        }
                        
                        if (endtast)
                            break; // TODO: might not be correct. Was : Exit For
                    }
                    if (endtast)
                        break; // TODO: might not be correct. Was : Exit For
                }
                if (endtast)
                    break; // TODO: might not be correct. Was : Exit For
            }
            return retfiles;
        }
    }
}
