using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using arCtl;
using Project.StateMachine;
using COMM;
using System.Windows.Forms;
using Project.ViewForm;
using AR;

namespace Project
{

    public partial class fMain
    {


        DateTime lastDeleteTime = DateTime.Now;
        DateTime startuptime = new DateTime(1982, 11, 23);
        enum EScreen
        {
            Auto = 0,
            Manual,
            IO,
            Flag
        }
        void SetScreen(System.Windows.Forms.Form newscreen)
        {
            if (newscreen == null)
                throw new Exception("화면전용용 폼이 Null 입니다. SM_RUN_INIT 에서 해당 폼이 초기화 되었는지 확인하세요");

            //작업시작
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action(() =>
                {
                    SetScreen(newscreen);
                }));
            }
            else
            {
                if (newscreen.GetType() == typeof(fManual))
                {

                }
                else if (PUB.DriveSpeed)
                {
                    var rlt = PUB.AGV.AGVCommand("SSH", PUB.setting.SPD_H.ToString("0000"));
                    if (rlt == arDev.eNarumiCommandResult.Success)
                    {
                        PUB.DriveSpeed = false;
                        PUB.log.Add($"Screen Change and DriveSpeed Off:{rlt}");
                    } else
                    {
                        PUB.log.AddE($"Screen Change and DriveSpeed Off:{rlt}");
                    }
                    
                }

                MenuAuto.ForeColor = Color.FromArgb(180, 180, 180);
                MenuFlag.ForeColor = Color.FromArgb(180, 180, 180);
                MenuLift.ForeColor = Color.FromArgb(180, 180, 180);
                MenuLog.ForeColor = Color.FromArgb(180, 180, 180);
                MenuMAN.ForeColor = Color.FromArgb(180, 180, 180);
                MenuAGV.ForeColor = Color.FromArgb(180, 180, 180);
                MenuBMS.ForeColor = Color.FromArgb(180, 180, 180);


                if (panDlg.Controls.Count > 0)
                {
                    var f = panDlg.Controls[0] as System.Windows.Forms.Form;
                    if (f.GetType() == newscreen.GetType()) return;
                    else f.Hide(); //숨김처리
                }
                panDlg.Controls.Clear();
                panDlg.Controls.Add(newscreen);
                newscreen.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
                newscreen.WindowState = System.Windows.Forms.FormWindowState.Maximized;
                newscreen.Show();
            }
        }

        string lockstep = string.Empty;
        System.Threading.ManualResetEvent mreloop = new System.Threading.ManualResetEvent(true);
        void sm_Running(object sender, StateMachine.StateMachine.RunningEventArgs e)
        {

            //창을 닫아야하는 상황에는 처리하지 않는다.
            if (PUB.popup.needClose)
            {
                System.Threading.Thread.Sleep(10); //팝업이 닫힐때까지 기다린다.
                PUB.sm.WaitFirstRun = true;
                return;
            }
            else PUB.sm.WaitFirstRun = false;

            if (mreloop.WaitOne(1) == false) return;
            mreloop.Reset();

            lockstep = e.Step.ToString();

            //main loop
            switch (e.Step)
            {
                case eSMStep.CLOSING:
                    _STEP_CLOSING_START(e.Step);
                    PUB.sm.SetNewStep(eSMStep.CLOSED);
                    break;
                case eSMStep.CLOSED:
                    if (e.isFirst) _STEP_CLOSED_START(e.Step);
                    else _STEP_CLOSED(e.Step, e.StepTime, e.StepTime);
                    break;
                case eSMStep.NOTSET:
                    PUB.log.Add("S/M Initialize Start");
                    PUB.sm.SetNewStep(eSMStep.INIT);
                    break;

                case eSMStep.INIT:  //최초실행이다.

                    if (_SM_RUN_INIT(e.isFirst, PUB.sm.StepRunTime))
                    {
                        //메인화면을 설정한다
                        form_auto = new ViewForm.fAuto();
                        form_manu = new ViewForm.fManual();
                        form_zlift = new ViewForm.fIO();
                        form_flag = new ViewForm.fFlag();
                        form_bms = new ViewForm.fBms();
                        form_agv = new ViewForm.fAgv();


                        form_auto.TopLevel = false;
                        form_manu.TopLevel = false;
                        form_zlift.TopLevel = false;
                        form_flag.TopLevel = false;
                        form_bms.TopLevel = false;
                        form_agv.TopLevel = false;


                        form_auto.Dock = System.Windows.Forms.DockStyle.Fill;
                        form_manu.Dock = System.Windows.Forms.DockStyle.Fill;
                        form_zlift.Dock = System.Windows.Forms.DockStyle.Fill;
                        form_flag.Dock = System.Windows.Forms.DockStyle.Fill;
                        form_bms.Dock = System.Windows.Forms.DockStyle.Fill;
                        form_agv.Dock = System.Windows.Forms.DockStyle.Fill;

                        SetScreen(form_auto);

                        PUB.sm.ResetRunStepSeq();
                        PUB.sm.SetNewStep(eSMStep.SYNC);
                        PUB.Speak(Lang.프로그램이초기화되었습니다);
                    }
                    break;


                case eSMStep.IDLE:

                    if (e.isFirst)
                    {
                        PUB.sm.bPause = false;
                        //Pub.flag.set(eFlag.UserStepCheck, false);
                        PUB.sm.ClearRunStep();
                        // Util_DO.SetMGZMotor(false);
                        PUB.Result.SMSG_ProgressEnable = false;
                        UpdateStatusMessage("준비 완료", Color.Red, Color.Gold);
                        if (startuptime.Year == 1982) startuptime = DateTime.Now;

                   
                        // 동기화 모드 종료 (혹시 남아있을 경우)
                        if (PUB._mapCanvas != null)
                        {
                            this.Invoke(new Action(() => {


                                AutoLoadLastPosition();

                                PUB._mapCanvas.ExitSyncMode( AGVNavigationCore.Controls.UnifiedAGVCanvas.CanvasMode.Run);
                            }));



                        }
                            
                    }

                    //자동소거기능
                    if (PUB.setting.AutoDeleteDay > 0)
                    {
                        if (VAR.BOOL[eVarBool.MINSPACE] == true)
                        {
                            var ts = DateTime.Now - lastDeleteTime;
                            if (ts.TotalSeconds > 1)
                            {
                                //파일을 찾아서 소거한다.
                                if (System.IO.Directory.Exists(PUB.path.FullName))
                                    DeleteFile(PUB.path.FullName);


                                lastDeleteTime = DateTime.Now;
                            }

                        }
                    }
                    break;

                case eSMStep.SYNC:
                    if (e.isFirst)
                    {
                        // 동기화 완료 시 캔버스 모드 복귀
                        this.Invoke(new Action(() => {
                            if (PUB._mapCanvas != null)
                                PUB._mapCanvas.SetSyncStatus("설정 동기화", 0f, "환경설정 값으로 AGV컨트롤러를 설정 합니다");
                        }));
                    }
                    if (_SM_RUN_SYNC(runStepisFirst, PUB.sm.GetRunSteptime))
                    {
                        var b1 = PUB.XBE.IsOpen;
                        var b2 = PUB.AGV.IsOpen;
                        var b3 = true;// PUB.PLC.IsOpen;
                        var b4 = PUB.BMS.IsOpen;

                        if (b1 == false || b2 == false || b3 == false || b4 == false)
                            PUB.Speak(Lang.하드웨어오류발생);
                        else
                            PUB.Speak( Lang.초기화완료);

                        PUB.sm.SetNewStep(eSMStep.IDLE);
                    }
                    break;

                case eSMStep.RUN:
                    _SM_RUN(e.isFirst, e.StepTime);
                    break;

                case eSMStep.PAUSE:
                case eSMStep.EMERGENCY:
                case eSMStep.ERROR:


                    //창을 닫아야하는 상황에는 처리하지 않는다.
                    if (PUB.popup.needClose)
                    {
                        System.Threading.Thread.Sleep(10); //팝업이 닫힐때까지 기다린다.
                        PUB.sm.WaitFirstRun = true;
                        return;
                    }
                    else PUB.sm.WaitFirstRun = false;

                    if (e.isFirst)
                    {

                        if (PUB.Result.ResultCode != eResult.NoError)
                        {
                            //에러메세지가 있는 경우에만 표시함
                            if (PUB.Result.ResultMessage != "")
                                PUB.popup.setMessage(PUB.Result.ResultMessage);

                            if (PUB.Result.ResultCode == eResult.Hardware)
                            {
                                PUB.Speak(Lang.하드웨어오류로인해진행할수없습니다);
                            }
                            else PUB.Speak(PUB.Result.ResultMessage);

                        }
                        if (e.Step == eSMStep.EMERGENCY) PUB.log.AddE("Enter Emergency Step");
                        else if (e.Step == eSMStep.PAUSE) PUB.log.AddE("Enter Pause Step : " + PUB.Result.ResultMessage);
                        else PUB.log.AddE(string.Format("Enter Error Step : {0}", PUB.Result.ResultMessage));



                        PUB.sm.bPause = false;
                        PUB.sm.ClearRunStep();
                        PUB.sm.SetNewStep(eSMStep.IDLE);
                    }
                    break;

                case eSMStep.RESET:

                    if (e.isFirst)
                    {
                        Resultclear();
                        PUB.sm.bPause = false;
                    }
                    else
                    {
                        if (_SM_RUN_RESET(runStepisFirst, PUB.sm.GetRunSteptime))
                            PUB.sm.SetNewStep(eSMStep.IDLE);
                    }
                    break;
            }

            mreloop.Set();
        }

        void DeleteFile(string path)
        {
            var basetime = DateTime.Now.AddDays(-1 * PUB.setting.AutoDeleteDay);
            var di = new System.IO.DirectoryInfo(path);
            if (di.Exists)
            {
                var dirYear = di.GetDirectories().OrderBy(t => t.Name).FirstOrDefault();
                if (dirYear != null)
                {
                    var dirMon = dirYear.GetDirectories().OrderBy(t => t.Name).FirstOrDefault();
                    if (dirMon != null)
                    {
                        var dirDay = dirMon.GetDirectories().OrderBy(t => t.Name).FirstOrDefault();
                        if (dirDay != null)
                        {
                            var curDay = DateTime.Parse(string.Format("{0}-{1}-{2} 00:00:00", dirYear.ToString(), dirMon.ToString(), dirDay.ToString()));
                            if (curDay < basetime)
                            {
                                var dirLot = dirDay.GetDirectories().OrderBy(t => t.Name).FirstOrDefault();
                                if (dirLot != null)
                                {
                                    var delfile = dirLot.GetFiles().FirstOrDefault();
                                    if (delfile != null)
                                    {
                                        try
                                        {
                                            PUB.log.AddI("Remove Fle : " + delfile.FullName + ",time=" + delfile.LastWriteTime.ToString());
                                            delfile.Delete();
                                        }
                                        catch (Exception ex)
                                        {
                                            PUB.log.AddE("deleete error : " + ex.Message);
                                        }
                                    }
                                    else
                                    {
                                        string delpath = dirLot.FullName;
                                        try
                                        {
                                            dirLot.Delete(true);
                                        }
                                        catch (Exception ex)
                                        {
                                            PUB.log.AddE("remove dir" + ex.Message + "," + delpath);
                                        }

                                    }
                                }
                                else
                                {
                                    //이 폴더아래에 다른 폴더가 하나도 없다 즉 비어 있따.
                                    string delpath = dirDay.FullName;
                                    try
                                    {
                                        dirDay.Delete(true);
                                    }
                                    catch (Exception ex)
                                    {
                                        PUB.log.AddE("remove dir" + ex.Message + "," + delpath);
                                    }
                                }
                            }

                        }
                        else
                        {
                            //날짜에 해당하는 폴더가 하나도 없다. 월 폴더를 제거한다.
                            string delpath = dirMon.FullName;
                            try
                            {
                                dirMon.Delete(true);
                            }
                            catch (Exception ex)
                            {
                                PUB.log.AddE("remove dir" + ex.Message + "," + delpath);
                            }
                        }
                    }
                    else
                    {
                        //이 달에 해당하는 데이터가 없다. 이 년도를 삭제한다.
                        string delpath = dirYear.FullName;
                        try
                        {
                            dirYear.Delete(true);
                        }
                        catch (Exception ex)
                        {
                            PUB.log.AddE("remove dir" + ex.Message + "," + delpath);
                        }
                    }
                }
                //년도별폴더목록을 정리함
                //가장작은 년도를 기준으로 파일을 검색해서 1개씩 삭제함
            }
        }

        void sm_Message(object sender, StateMachine.StateMachine.StateMachineMessageEventArgs e)
        {
            //상태머신에서 발생한 메세지
            if (e.Header != "SM-STEP")
                PUB.log.Add(e.Header, e.Message);
        }


        void sm_StepChanged(object sender, StateMachine.StateMachine.StepChangeEventArgs e)
        {
            //상태머신의 스텝이 변경될때 발생함
            PUB.logdebug.Add($"[AI_TRACE] Global State Change: {e.Old} -> {e.New}");
            //Pub.log.Add(string.Format("SM:Step Changed {0} to {1}",e.Old,e.New));
            VAR.BOOL[eVarBool.FLAG_AUTORUN] = e.New == eSMStep.RUN;
            VAR.BOOL[eVarBool.FLAG_SYNC] = (e.New == eSMStep.SYNC);

            //230313
            var n = (eSMStep)e.New;
            EEMStatus.AddStatusSQL(n, extrun: true);

            if (e.New == eSMStep.IDLE)
            {
                VAR.TIME[eVarTime.IdleStart] = DateTime.Now;
                PUB.AGV.AGVMoveStop("_sm_stepchange", arDev.Narumi.eStopOpt.Stop);

                if (VAR.BOOL[eVarBool.FLAG_CHARGEONA] || VAR.BOOL[eVarBool.FLAG_CHARGEONM])
                    PUB.AGV.AGVCharge(PUB.setting.ChargerID, false);

                if (VAR.BOOL[eVarBool.FLAG_AUTORUN])
                {
                    PUB.logagv.Add($"IDLE 전환으로인해 autorun 해제");
                    VAR.BOOL[eVarBool.FLAG_AUTORUN] = false;
                }
            }
        }

        //void uploadForm_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
        //{
        //    //이벤트 해제
        //    if (uploadForm != null)
        //        uploadForm.FormClosed -= uploadForm_FormClosed;

        //    //업로드 창이 닫히면 그 결과를 화면에 표시 해준다.
        //    //foreach (System.Windows.Forms.ListViewItem lv in uploadForm.listView1.Items)
        //    //{
        //    //    string slot = lv.SubItems[0].Text;
        //    //    string wafer = lv.SubItems[2].Text;
        //    //    string state = lv.SubItems[3].Text;

        //    //}
        //}
    }
}
