using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using libPayService;

using INT63DC_2C.DialogForms;
using INT63DC_2C.Part11_UserManager;
using INT63DC_ImageDll;

namespace INT63DC_2C.Forms
{
    public partial class FormProgramUpdate : Form
    {
        #region Field
        private FormMain m_ParentForm;
        private DataStore.E_Step3 UpdateStep;

        private bool IsUpdate = false;

        private int Check;

        private string USBPath = "";
        private string UpdateFilePath = "";
        private string OldFilePath = "";
        private string RemoveFolderPath = "";
        private string KeyFolderPath = "";

        private List<string> DllName = new List<string>();
        private List<long> LongOldDllFileLastWriteTime = new List<long>();
        private List<long> LongNewDllFileLastWriteTime = new List<long>();
        #endregion

        #region Constructor
        public FormProgramUpdate(FormMain parent)
        {
            InitializeComponent();

            this.ParentForm = parent;

            this.InitializeDesign();
            this.DefaultSetting();
        }
        #endregion

        #region Property
        public FormMain ParentForm
        {
            get { return this.m_ParentForm; }
            private set { this.m_ParentForm = value; }
        }
        #endregion

        #region Method
        private void InitializeDesign()
        {
            ImageDll images = new ImageDll();

            switch (this.ParentForm.SystemConfig.Language)
            {
                case DataStore.E_LanguageID.Korean:
                    break;
                case DataStore.E_LanguageID.English:
                    #region English
                    this.labelTitle.Text = "Program Update";

                    this.buttonLCD.Text = "LCD";
                    this.buttonServiceUpdate.Font = new Font("새굴림", 16, FontStyle.Bold);
                    this.buttonServiceUpdate.Text = "Service Update";

                    this.buttonBack.DisableImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.engBackDisable));
                    this.buttonBack.DownImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.engBackDown));
                    this.buttonBack.UpImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.engBackUp));
                    #endregion
                    break;
                case DataStore.E_LanguageID.Chinese:
                    #region Chinese
                    this.labelTitle.Text = "更新";

                    this.buttonLCD.Text = "液晶显示屏";
                    this.buttonServiceUpdate.Font = new Font("새굴림", 16, FontStyle.Bold);
                    this.buttonServiceUpdate.Text = "服务更新";

                    this.buttonBack.DisableImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.chnBackDisable));
                    this.buttonBack.DownImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.chnBackDown));
                    this.buttonBack.UpImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.chnBackUp));
                    #endregion
                    break;
                case DataStore.E_LanguageID.Czech:
                    #region Czech
                    this.labelTitle.Text = "Aktualizace";
                    #endregion
                    break;
                case DataStore.E_LanguageID.German:
                    #region German
                    this.labelTitle.Text = "Aktualisierung";

                    this.buttonLCD.Text = "LCD";
                    this.buttonServiceUpdate.Font = new Font("새굴림", 10, FontStyle.Regular);
                    this.buttonServiceUpdate.Text = "Service-Aktualisierung";

                    this.buttonBack.DisableImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.gerBackDisable));
                    this.buttonBack.DownImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.gerBackDown));
                    this.buttonBack.UpImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.gerBackUp));
                    #endregion
                    break;
                case DataStore.E_LanguageID.Japanese:
                    #region Japanese
                    this.labelTitle.Text = "更新";

                    this.buttonLCD.Text = "LCD";
                    this.buttonServiceUpdate.Text = "Service Update";

                    this.buttonBack.DisableImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.jpnBackDisable));
                    this.buttonBack.DownImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.jpnBackDown));
                    this.buttonBack.UpImage = new Bitmap(images.GetImage(ImageDll.ButtonImages.jpnBackUp));
                    #endregion
                    break;
                default:
                    break;
            }
        }
        private void DefaultSetting()
        {
            PayService.ServiceDataEvent += PayService_ServiceDataEvent;
            this.DecideUpdatePath();
        }
        private void DecideUpdatePath()
        {
            if (Directory.Exists("Hard Disk\\") == true)
                this.USBPath = "Hard Disk\\";
            else if (Directory.Exists("하드 디스크\\") == true)
                this.USBPath = "하드 디스크\\";
            else
                this.USBPath = "하드 디스크\\";

            this.UpdateFilePath = this.USBPath + "UpdateFiles\\";
            this.KeyFolderPath = this.USBPath + "KEY\\";
            this.OldFilePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\";
            if (this.OldFilePath.StartsWith("\\F") == true)
                this.RemoveFolderPath = "Flash Disk\\RemoveFile\\";
            else
                this.RemoveFolderPath = "SD Card\\RemoveFile\\";
        }

        private void InitialStatus()
        {
            this.UpdateStep = DataStore.E_Step3.Step1;
            this.UpdateLabelStatus(this.UpdateStep, this.ParentForm.SystemConfig.Language);
            this.buttonLCD.Enabled = true;
            this.buttonServiceUpdate.Enabled = true;
            this.labelMessage2.ForeColor = Color.Black;
            this.labelMessage2.Visible = true;
            this.buttonBack.Enabled = true;
        }
        private void FinishStatusNeededReBoot()
        {
            this.ParentForm.Enabled = false;
            this.UpdateStep = DataStore.E_Step3.Step3;
            this.UpdateLabelStatus(this.UpdateStep, this.ParentForm.SystemConfig.Language);
        }

        public void EnableBackupButton(bool enable)
        {
            this.buttonLCD.Enabled = enable;
            this.buttonServiceUpdate.Enabled = enable;

            if (enable == true)
            {
                this.buttonLCD.TextColor = Color.Black;
                this.buttonServiceUpdate.TextColor = Color.Black;
            }
            else
            {
                this.buttonLCD.TextColor = Color.DimGray;
                this.buttonServiceUpdate.TextColor = Color.DimGray;
            }
            this.Refresh();
        }

        private void ProgramUpdateCheck(DialogResult result)
        {
            PayService service = new PayService();
            DataStore.E_UpdateCheck check = DataStore.E_UpdateCheck.Fail;

            if (result == DialogResult.Yes)
            {
                check = this.CheckError();

                if (check == DataStore.E_UpdateCheck.Success)
                {
                    this.buttonLCD.TextColor = Color.DimGray;
                    this.buttonLCD.Enabled = false;
                    this.buttonServiceUpdate.TextColor = Color.DimGray;
                    this.buttonServiceUpdate.Enabled = false;
                    this.UpdateStep = DataStore.E_Step3.Step2;
                    this.UpdateLabelStatus(this.UpdateStep, this.ParentForm.SystemConfig.Language);

                    if (this.IsUpdate == true)
                        this.ProgramUpdate();
                    else
                    {
                        FileInfo[] newFiles;
                        DirectoryInfo directoryFolder = new DirectoryInfo(this.KeyFolderPath);
                        if (directoryFolder.Exists == false)
                            directoryFolder.Create();

                        newFiles = directoryFolder.GetFiles();

                        //Console.Write("{0}, {1} \n", this.KeyFolderPath + newFiles[0].ToString(), newFiles.Length);

                        ErrorLog_e ret = service.PayServiceOpen(this.KeyFolderPath + newFiles[0].ToString(), this.ParentForm.SystemConfig.SerialNumber);
                        if (ret != ErrorLog_e.NONE)
                        {
                            DialogFormMessage message = new DialogFormMessage((int)ret, this.ParentForm.SystemConfig.Language,
                                this.ParentForm.SystemConfig.CurrentForm);
                            message.ShowDialog();

                            this.InitialStatus();
                        }
                    }
                }
                else if (check == DataStore.E_UpdateCheck.NotUsbMomery)
                {
                    DialogFormMessage message = new DialogFormMessage(5, this.ParentForm.SystemConfig.Language);
                    message.ShowDialog();
                    this.IsUpdate = false;
                }
                else if (check == DataStore.E_UpdateCheck.NotUpdateFolder)
                {
                    DialogFormMessage message = new DialogFormMessage(9, this.ParentForm.SystemConfig.Language);
                    message.ShowDialog();
                    this.IsUpdate = false;
                }
                else if (check == DataStore.E_UpdateCheck.NotFile)
                {
                    DialogFormMessage message = new DialogFormMessage(7, this.ParentForm.SystemConfig.Language);
                    message.ShowDialog();
                    this.IsUpdate = false;
                }
                else if (check == DataStore.E_UpdateCheck.TooManyFiles)
                {
                    DialogFormMessage message = new DialogFormMessage(8, this.ParentForm.SystemConfig.Language);
                    message.ShowDialog();
                    this.IsUpdate = false;
                }
            }
        }
        public DataStore.E_UpdateCheck CheckError()
        {
            DataStore.E_UpdateCheck ret = DataStore.E_UpdateCheck.Fail;
            FileInfo[] newFiles;

            DirectoryInfo info = new DirectoryInfo(this.USBPath);
            DirectoryInfo dirFolderSource;

            if (this.IsUpdate == true)
                dirFolderSource = new DirectoryInfo(this.UpdateFilePath);
            else
                dirFolderSource = new DirectoryInfo(this.KeyFolderPath);

            // USB 장착 유무 확인
            if (info.Exists == true)
            {
                // USB에 UpdateFiles 유무 확인
                if (dirFolderSource.Exists == true)
                {
                    newFiles = dirFolderSource.GetFiles();

                    if (newFiles.Length == 0)
                    {
                        ret = DataStore.E_UpdateCheck.NotFile;
                    }
                    else
                    {
                        if (this.IsUpdate == false)
                        {
                            if (newFiles.Length == 1)
                                ret = DataStore.E_UpdateCheck.Success;
                            else
                                ret = DataStore.E_UpdateCheck.TooManyFiles;
                        }
                        else
                            ret = DataStore.E_UpdateCheck.Success;
                    }
                }
                else
                {
                    ret = DataStore.E_UpdateCheck.NotUpdateFolder;
                }
            }
            else
            {
                ret = DataStore.E_UpdateCheck.NotUsbMomery;
            }

            return ret;
        }

        private void ProgramUpdate()
        {
            this.buttonBack.Enabled = false;

            FileInfo[] newFiles;
            DirectoryInfo directoryFolderUpdateFiles = new DirectoryInfo(this.UpdateFilePath);
            if (directoryFolderUpdateFiles.Exists == false)
                directoryFolderUpdateFiles.Create();

            newFiles = directoryFolderUpdateFiles.GetFiles();

            this.progressBarUpdate.Value += 20;

            this.TreatmentRemoveOldFile();

            this.progressBarUpdate.Value += 20;

            this.TreatmentCopyNewFile(newFiles);

            this.progressBarUpdate.Value += 100;
            this.ParentForm.SetTrackingHistoryData(DataStore.E_TrackingOperation.Update, "LCD");
            this.FinishStatusNeededReBoot();
        }
        private void TreatmentRemoveOldFile()
        {
            bool removeFolderCheck = false;
            FileInfo[] oldFiles;
            DirectoryInfo directoryFolderRun = new DirectoryInfo(this.OldFilePath);
            DirectoryInfo directoryFolderRemove = new DirectoryInfo(this.RemoveFolderPath);

            removeFolderCheck = directoryFolderRemove.Exists;
            oldFiles = directoryFolderRun.GetFiles();

            if (removeFolderCheck == false)
                directoryFolderRemove.Create();

            foreach (FileInfo subFile in oldFiles)
                subFile.MoveTo(this.RemoveFolderPath + DateTime.Now.ToString("yyyyMMddHHmmss") + subFile.Name.ToString());

            this.progressBarUpdate.Value += 20;
        }
        private void TreatmentCopyNewFile(FileInfo[] newFile)
        {
            // 새 파일 복사
            foreach (FileInfo subFile in newFile)
                subFile.CopyTo(this.OldFilePath + subFile.Name.ToString());

            this.progressBarUpdate.Value += 20;

        }

        private void UpdateLabelStatus(DataStore.E_Step3 step, DataStore.E_LanguageID language)
        {
            switch (step)
            {
                case DataStore.E_Step3.Step1:
                    #region Step1
                    switch (language)
                    {
                        case DataStore.E_LanguageID.Korean:
                            this.labelMessage1.Text = "USB를 본체에 삽입 하십시오";
                            this.labelMessage2.Text = "업데이트 할 항목을 선택해 주십시오";
                            break;
                        case DataStore.E_LanguageID.English:
                            this.labelMessage1.Text = "Please insert usb into the device";
                            this.labelMessage2.Text = "Please select an item to update";
                            break;
                        case DataStore.E_LanguageID.Chinese:
                            this.labelMessage1.Text = "请将usb插入设备中。";
                            this.labelMessage2.Text = "请选择一个项目来更新";
                            break;
                        case DataStore.E_LanguageID.German:
                            this.labelMessage1.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage1.Text = "USB nicht vom Gerät trennen";
                            this.labelMessage2.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage2.Text = "Drücken Sie nach dem USB-Anschluss die untere Taste";
                            break;
                        default:
                            break;
                    }
                    #endregion
                    break;
                case DataStore.E_Step3.Step2:
                    #region Step2
                    switch (language)
                    {
                        case DataStore.E_LanguageID.Korean:
                            this.labelMessage1.Text = "업데이트 중...";
                            this.labelMessage2.Text = "USB를 본체에서 분리하지 마십시오";
                            break;
                        case DataStore.E_LanguageID.English:
                            this.labelMessage1.Text = "Updating...";
                            this.labelMessage2.Text = "Do not remove the USB from the device";
                            break;
                        case DataStore.E_LanguageID.Chinese:
                            this.labelMessage1.Text = "更新中...";
                            this.labelMessage2.Text = "请勿断开USB";
                            break;
                        case DataStore.E_LanguageID.German:
                            this.labelMessage1.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage1.Text = "Aktualisierung….";
                            this.labelMessage2.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage2.Text = "USB nicht vom Gerät trennen";
                            break;
                        default:
                            break;
                    }
                    #endregion
                    break;
                case DataStore.E_Step3.Step3:
                    #region Step3
                    this.labelMessage2.ForeColor = Color.Red;
                    switch (language)
                    {
                        case DataStore.E_LanguageID.Korean:
                            this.labelMessage1.Text = "프로그램 업데이트 완료";
                            this.labelMessage2.Text = "전원을 끄고 다시 켜주세요";
                            break;
                        case DataStore.E_LanguageID.English:
                            this.labelMessage1.Text = "Program update complete";
                            this.labelMessage2.Text = "Reset the system";
                            break;
                        case DataStore.E_LanguageID.Chinese:
                            this.labelMessage1.Text = "系统更新完成";
                            this.labelMessage2.Text = "关掉电源，然后在打开电源";
                            break;
                        case DataStore.E_LanguageID.German:
                            this.labelMessage1.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage1.Text = "Programmaktualisierung abgeschlossen";
                            this.labelMessage2.Font = new Font("새굴림", 18, FontStyle.Bold);
                            this.labelMessage2.Text = "Mit dem Hauptschalter aus- und einschalten";
                            break;
                        default:
                            break;
                    }
                    #endregion
                    break;
                default:
                    break;
            }

            this.Refresh();
        }

        private void PayService_ServiceDataEvent(SERVICE_ITEMS_e item, SERVICE_MODE_e value)
        {
            //Console.Write("{0} = {1} \n", item.ToString(), value.ToString());
            this.progressBarUpdate.Value = 50;

            //Console.Write("{0}, {1} \n", item.ToString(), value.ToString());

            switch (item)
            {
                case SERVICE_ITEMS_e.MODBUS:
                    #region Modbus
                    switch (value)
                    {
                        case SERVICE_MODE_e.DISABLE:
                            if (this.ParentForm.SystemConfig.IsModbus == true)
                            {
                                this.ParentForm.SystemConfig.IsModbus = false;

                                if (this.ParentForm.SystemConfig.Serial3Mode == (int)DataStore.E_CommMode.f99_Modbus)
                                    this.ParentForm.SystemConfig.Serial3Mode = 0;
                                if (this.ParentForm.SystemConfig.EthernetMode == (int)DataStore.E_CommMode.f99_Modbus)
                                    this.ParentForm.SystemConfig.EthernetMode = 0;

                                this.ParentForm.SaveSystemConfigurationFile3(this.ParentForm.SystemConfig);

                                //this.ParentForm.CenterConfiSerial.ChangeCommunicationMode();
                                //this.ParentForm.CenterConfiEthernet.ChangeCommunicationMode();

                                this.labelUpdateContents.Text += "Modbus OFF";
                                this.ParentForm.SetTrackingHistoryData(DataStore.E_TrackingOperation.FunctionUpdate, "Modbus_OFF");
                            }
                            break;
                        case SERVICE_MODE_e.ENABLE:
                            if (this.ParentForm.SystemConfig.IsModbus == false)
                            {
                                this.ParentForm.SystemConfig.IsModbus = true;
                                this.ParentForm.SaveSystemConfigurationFile3(this.ParentForm.SystemConfig);

                                //this.ParentForm.CenterConfiSerial.ChangeCommunicationMode();
                                //this.ParentForm.CenterConfiEthernet.ChangeCommunicationMode();

                                this.labelUpdateContents.Text += "Modbus ON";
                                this.ParentForm.SetTrackingHistoryData(DataStore.E_TrackingOperation.FunctionUpdate, "Modbus_ON");
                            }
                            break;
                        default:
                            break;
                    }
                    this.buttonBack.Enabled = false;
                    #endregion
                    break;
                case SERVICE_ITEMS_e.PART11:
                    #region Part11
                    switch (value)
                    {
                        case SERVICE_MODE_e.DISABLE:
                            if (this.ParentForm.SystemConfig.IsPart11 == true)
                            {
                                this.ParentForm.SystemConfig.IsPart11 = false;
                                this.ParentForm.SystemConfig.IsLogin = false;
                                this.ParentForm.SystemConfig.IsOptDataStatistics = false;
                                this.ParentForm.SystemConfig.IsDataBackup = false;

                                if (this.ParentForm.SystemConfig.StoragePeriod > 12)
                                    this.ParentForm.SystemConfig.StoragePeriod = 12;

                                // Delete user list
                                UserManager.UserManager_UserAllDel();

                                this.ParentForm.SaveSystemConfigurationFile1(this.ParentForm.SystemConfig);
                                this.ParentForm.SaveSystemConfigurationFile2(this.ParentForm.SystemConfig);

                                if (this.labelUpdateContents.Text.Length != 0)
                                    this.labelUpdateContents.Text += ",  ";
                                this.labelUpdateContents.Text += "Part11 OFF";
                                this.ParentForm.SetTrackingHistoryData(DataStore.E_TrackingOperation.FunctionUpdate, "Part11_OFF");
                            }
                            break;
                        case SERVICE_MODE_e.ENABLE:
                            if (this.ParentForm.SystemConfig.IsPart11 == false)
                            {
                                this.ParentForm.SystemConfig.IsLogin = true;
                                this.ParentForm.SystemConfig.IsPart11 = true;
                                this.ParentForm.SystemConfig.IsOptDataStatistics = true;
                                this.ParentForm.SystemConfig.IsDataBackup = true;

                                if (this.ParentForm.SystemConfig.StoragePeriod <= 12)
                                    this.ParentForm.SystemConfig.StoragePeriod = 24;

                                this.ParentForm.SaveSystemConfigurationFile1(this.ParentForm.SystemConfig);
                                this.ParentForm.SaveSystemConfigurationFile2(this.ParentForm.SystemConfig);

                                if (this.labelUpdateContents.Text.Length != 0)
                                    this.labelUpdateContents.Text += ",  ";
                                this.labelUpdateContents.Text += "Part11 ON";
                                this.ParentForm.SetTrackingHistoryData(DataStore.E_TrackingOperation.FunctionUpdate, "Part11_ON");
                            }
                            break;
                        default:
                            break;
                    }

                    this.FinishStatusNeededReBoot();
                    this.progressBarUpdate.Value += 100;
                    this.buttonBack.Enabled = false;
                    #endregion
                    break;
                default:
                    break;
            }

            this.labelTitleUpdate.Visible = true;
            this.labelUpdateContents.Visible = true;
        }

        public void DisplayRefresh()
        {
            this.ParentForm.SystemConfig.CurrentForm = DataStore.FormStore.FormProgramUpdate;

            this.InitialStatus();
            this.progressBarUpdate.Value = 0;

            // USB 체크
            DirectoryInfo info = new DirectoryInfo("하드 디스크\\");
            if (info.Exists == true)
            {
                this.buttonLCD.TextColor = Color.Black;
                this.buttonLCD.Enabled = true;
                this.buttonServiceUpdate.TextColor = Color.Black;
                this.buttonServiceUpdate.Enabled = true;
            }
            else
            {
                this.buttonLCD.TextColor = Color.DimGray;
                this.buttonLCD.Enabled = false;
                this.buttonServiceUpdate.TextColor = Color.DimGray;
                this.buttonServiceUpdate.Enabled = false;
            }
        }
        #endregion

        #region Event Handler
        private void buttonLCD_Click(object sender, EventArgs e)
        {
            DialogFormYesNo myDlg = new DialogFormYesNo(this.ParentForm.SystemConfig.Language, 3);
            DialogResult dr = myDlg.ShowDialog();
            if (dr == DialogResult.Yes)
                this.IsUpdate = true;

            myDlg.Close();

            this.Refresh();

            this.labelMessage2.Visible = true;
            this.ProgramUpdateCheck(dr);
        }
        private void buttonServiceUpdate_Click(object sender, EventArgs e)
        {
            DialogFormYesNo myDlg = new DialogFormYesNo(this.ParentForm.SystemConfig.Language, 3);
            DialogResult dr = myDlg.ShowDialog();
            myDlg.Close();

            PayService service = new PayService();

            this.labelMessage2.Visible = true;
            this.ProgramUpdateCheck(dr);
        }

        private void buttonBack_Click(object sender, EventArgs e)
        {
            this.ParentForm.ChildFormMenu.DisplayRefresh();
            ((FormMain)(Owner)).smartForm.Show((int)DataStore.FormStore.FormMenu);
        }

        private void timerUpdate_Tick(object sender, EventArgs e)
        {
            this.Check += 1;
            if (this.Check == 3)
            {
                this.ProgramUpdate();
            }

            if (this.progressBarUpdate.Value == 100)
            {
                this.labelMessage1.Visible = false;
                this.labelMessage2.Visible = false;
            }
        }
        #endregion
    }
}