using EVCB_OCPP.Domain;
using EVCB_OCPP.Domain.Models.Database;
using EVCB_OCPP.Packet.Features;
using EVCB_OCPP.Packet.Messages;
using EVCB_OCPP.Packet.Messages.Core;
using Microsoft.Win32;
using Newtonsoft.Json;
using OCPPPackage.Profiles;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.Entity;
using EVCB_OCPP.Packet.Messages.RemoteTrigger;
using EVCB_OCPP.Packet.Messages.SubTypes;
using EVCB_OCPP.Packet.Messages.LocalAuthListManagement;
using EVCB_OCPP.Packet.Messages.FirmwareManagement;
using EVCB_OCPP.Packet.Messages.Reservation;
using EVCB_OCPP.Packet.Messages.SmartCharging;
using System.Threading;
using System.Net.Http;
using Newtonsoft.Json.Converters;

namespace TestTool.RemoteTriggerAPP
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {

        string action = "";
        List<UploadFile> publishes = new List<UploadFile>();
        FTPClient UploadClient = new FTPClient(@"ftp://test.evsocket.phihong.com.cn", "testocpp", "testocpp");
        string chargingProfilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SetChargingProfile.json");
        string dataTransferPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DataTransfer.json");
        int selectedPublish = -1;
        bool isDestroyMode = false;
        public MainWindow()
        {
            var oo = new { idToken = "3345678", price = "Connection Fee: $2.11 NTD/time; Current Rate: $2.22 NTD/kWh;Occupancy Fee: $2.33 NTD/hr; Account Balance: $2444 NTD" };


            var tt = new DataTransferRequest()
            {
                vendorId = "Phihong Technology",
                messageId = "SetUserPrice",
                data = JsonConvert.SerializeObject(oo)
            };

            var ttt = JsonConvert.SerializeObject(tt);


            InitializeComponent();
            Loaded += MainWindow_Loaded;
            UploadClient.OnUploadProgress += UploadClient_OnUploadProgress;

        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            uxChargeBoxIdTb.Text = Properties.Settings.Default.ChargeBoxId;
        }

        private void UxSubmitBtn_Click(object sender, RoutedEventArgs e)
        {
            if (isDestroyMode)
            {
                try
                {
                    string actualAction = action.Split(new char[] { '_', '(' })[0];
                    var uuid = Guid.NewGuid().ToString();
                    WritetoDB(uuid, null, actualAction, GetDestroyVersionData(actualAction));
                    uxMsgTb.Text = string.Format("Send Actions: {0} UUID:{1}", actualAction, uuid);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

            }
            else
            {
                switch (action)
                {
                   
                    #region Core Profile
                    case "ChangeAvailability_Inoperative":
                        {
                            SetChangeAvailability_Inoperative();
                        }
                        break;
                    case "ChangeAvailability_Operative":
                        {
                            SetChangeAvailability_Operative();
                        }
                        break;
                    case "DataTransfer":
                        {
                            var request = VerifyDataTransfer(dataTransferPath);
                            SetDataTransfer(request);
                        }
                        break;
                    case "GetConfiguration":
                        {
                            if (uxConfigKeyTb.Text == "")
                            {
                                SetGetConfiguration_ALL();
                            }
                            else
                            {
                                SetGetConfiguration();
                            }

                        }
                        break;
                    case "ChangeConfiguration":
                        {
                            SetChangeConfiguration();

                        }
                        break;
                    case "ClearCache":
                        {
                            SetClearCache();
                        }
                        break;
                    case "RemoteStartTransaction":
                        {
                            SetRemoteStartTransaction();
                        }
                        break;
                    case "RemoteStartTransaction_ChargingProfile":
                        {
                            var chargingProfile = VerifyChargingProfile(chargingProfilePath);
                            if (chargingProfile != null)
                            {
                                SetRemoteStartTransaction(chargingProfile);
                            }
                            else
                            {
                                uxMsgTb.Text = "Please check chargingProfile.json exist in " + AppDomain.CurrentDomain.BaseDirectory;
                            }

                        }
                        break;
                    case "RemoteStopTransaction":
                        {
                            SetRemoteStopTransaction();
                        }
                        break;
                    case "Reset_HardReset":
                        {
                            SetHardReset();
                        }
                        break;
                    case "Reset_SoftReset":
                        {
                            SetSoftReset();
                        }
                        break;
                    case "UnlockConnector":
                        {
                            SetUnlockConnector();
                        }

                        break;
                    #endregion
                    #region Local Authorization
                    case "GetLocalListVersion":
                        {
                            GetLocalListVersion();
                        }
                        break;
                    case "SendLocalList_Full":
                        {
                            SendLocalAuthorizationList(true);
                        }
                        break;
                    case "SendLocalList_Diff":
                        {
                            SendLocalAuthorizationList(false);
                        }
                        break;
                    #endregion
                    case "GetDiagnostics_FTP":
                        {
                            GetDiagnostics(true);
                        }
                        break;
                    case "GetDiagnostics_HTTP":
                        {
                            GetDiagnostics(false);
                        }
                        break;
                    case "ReserveNow":
                        {
                            ReserveNow();
                        }
                        break;
                    case "CancelReservation":
                        {
                            CancelReservation();
                        }
                        break;
                    case "ClearChargingProfile":
                        {
                            ClearChargingProfile();
                        }
                        break;
                    case "GetCompositeSchedule":
                        {
                            GetCompositeSchedule();
                        }
                        break;
                    case "SetChargingProfile":
                        {
                            var chargingProfile = VerifyChargingProfile(chargingProfilePath);
                            if (chargingProfile != null)
                            {
                                SetChargingProfile(chargingProfile);
                            }
                            else
                            {
                                uxMsgTb.Text = "Please check chargingProfile.json exist in " + AppDomain.CurrentDomain.BaseDirectory;
                            }

                            //SetChargingProfile(new SetChargingProfileRequest()
                            //{
                            //    connectorId = 0,
                            //    csChargingProfiles = new csChargingProfiles()
                            //    {
                            //        chargingProfileId = 1,
                            //        chargingProfileKind = ChargingProfileKindType.Recurring,
                            //        chargingProfilePurpose = ChargingProfilePurposeType.ChargePointMaxProfile,
                            //        chargingSchedule = new ChargingSchedule()
                            //        {
                            //            chargingRateUnit = ChargingRateUnitType.W,
                            //            chargingSchedulePeriod = new List<ChargingSchedulePeriod>()
                            //                            {
                            //                                new ChargingSchedulePeriod(){  startPeriod=0, limit=int.Parse(uxConfigValueTb.Text)}
                            //                            },


                            //        },
                            //        recurrencyKind = RecurrencyKindType.Daily,
                            //        stackLevel = 1,

                            //    }
                            //});

                        }
                        break;

                    #region Trigger Profile
                    case "TriggerMessage_BootNotification":
                    case "TriggerMessage_DiagnosticsStatusNotification":
                    case "TriggerMessage_FirmwareStatusNotification":
                    case "TriggerMessage_Heartbeat":
                    case "TriggerMessage_MeterValues":
                    case "TriggerMessage_StatusNotification":
                        {
                            SetRemoteTrigger(action);
                        }
                        break;
                    #endregion
                    default:
                        break;

                }
            }

        }

        private void SetDataTransfer(DataTransferRequest request)
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private DataTransferRequest VerifyDataTransfer(string path)
        {
            DataTransferRequest request = null;

            if (!File.Exists(path)) return request;

            try
            {
                request = JsonConvert.DeserializeObject<DataTransferRequest>(File.ReadAllText(path));
            }
            catch
            {

            }
            return request;
        }

        private SetChargingProfileRequest VerifyChargingProfile(string path)
        {
            SetChargingProfileRequest request = null;

            if (!File.Exists(path)) return request;

            try
            {
                request = JsonConvert.DeserializeObject<SetChargingProfileRequest>(File.ReadAllText(path));
            }
            catch
            {

            }
            return request;
        }


        private void SetChargingProfile(SetChargingProfileRequest csProfile)
        {
            try
            {

                var uuid = Guid.NewGuid().ToString();

                WritetoDB(uuid, csProfile);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void GetCompositeSchedule()
        {
            try
            {

                var uuid = Guid.NewGuid().ToString();
                var request = new GetCompositeScheduleRequest()
                {
                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
                    duration = 10000
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void ClearChargingProfile()
        {
            try
            {

                var uuid = Guid.NewGuid().ToString();
                var request = new ClearChargingProfileRequest()
                {
                    connectorId = Convert.ToInt32(uxConnectorIdTb.Text),

                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void CancelReservation()
        {

            try
            {

                var uuid = Guid.NewGuid().ToString();
                var request = new CancelReservationRequest()
                {
                    reservationId = Convert.ToInt32(uxReservationTb.Text),
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetWrongAction()
        {
            bool isError = false;
            DateTime expiryTime = DateTime.Now;
            try
            {
                try
                {
                    expiryTime = Convert.ToDateTime(uxExpiryTimeTb.Text);
                    //if (expiryTime < DateTime.Now.AddSeconds(60))
                    //{
                    //    isError = true;
                    //    uxMsgTb.Text = string.Format("ExpiryTime is too close or too early to the current time (60 seconds).");
                    //}

                }
                catch (Exception ex)
                {
                    if (ex is FormatException)
                    {
                        isError = true;
                        uxMsgTb.Text = string.Format("ExpiryTime's Format is wrong Example:{0}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
                    }
                }
                if (!isError)
                {
                    var uuid = Guid.NewGuid().ToString();
                    var request = new ReserveNowRequest()
                    {
                        connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
                        expiryDate = expiryTime.ToUniversalTime(),
                        idTag = uxIdTagTb.Text,
                        parentIdTag = "PTAG",
                        reservationId = Convert.ToInt32(expiryTime.ToUniversalTime().ToString("yyMMddHHmm")),

                    };

                    WritetoDB(uuid, request);
                    uxMsgTb.Text = string.Format("UUID:{0}", uuid);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void ReserveNow()
        {
            bool isError = false;
            DateTime expiryTime = DateTime.Now;
            try
            {
                try
                {
                    expiryTime = Convert.ToDateTime(uxExpiryTimeTb.Text);
                    //if (expiryTime < DateTime.Now.AddSeconds(60))
                    //{
                    //    isError = true;
                    //    uxMsgTb.Text = string.Format("ExpiryTime is too close or too early to the current time (60 seconds).");
                    //}

                }
                catch (Exception ex)
                {
                    if (ex is FormatException)
                    {
                        isError = true;
                        uxMsgTb.Text = string.Format("ExpiryTime's Format is wrong Example:{0}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
                    }
                }
                if (!isError)
                {
                    var uuid = Guid.NewGuid().ToString();
                    var request = new ReserveNowRequest()
                    {
                        connectorId = Convert.ToInt32(uxConnectorIdTb.Text),
                        expiryDate = expiryTime.ToUniversalTime(),
                        idTag = uxIdTagTb.Text,
                        parentIdTag = "PTAG",
                        reservationId = Convert.ToInt32(expiryTime.ToUniversalTime().ToString("yyMMddHHmm")),

                    };

                    WritetoDB(uuid, request);
                    uxMsgTb.Text = string.Format("UUID:{0}", uuid);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void GetDiagnostics(bool ftp)
        {
            try
            {

                var uuid = Guid.NewGuid().ToString();
                var request = new GetDiagnosticsRequest()
                {

                    location = new Uri(ftp ? Properties.Settings.Default.FTPGetDiagnosticsPreUrl : Properties.Settings.Default.GetDiagnosticsPreUrl),
                    retries = 1,
                    retryInterval = 30,
                    startTime = DateTime.Now.AddHours(-1).ToUniversalTime(),
                    stopTime = DateTime.Now.ToUniversalTime()


                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        #region Local Authorization

        private void GetLocalListVersion()
        {
            try
            {

                var uuid = Guid.NewGuid().ToString();
                var request = new GetLocalListVersionRequest()
                {

                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SendLocalAuthorizationList(bool isFull)
        {
            try
            {
                var size = Convert.ToInt32(uxLocalListSizeTb.Text);
                var uuid = Guid.NewGuid().ToString();
                var request = new SendLocalListRequest()
                {
                    listVersion = Convert.ToInt32(DateTimeOffset.Now.AddDays(-50).ToUnixTimeSeconds()),
                    updateType = isFull ? UpdateType.Full : UpdateType.Differential,
                    localAuthorizationList = new List<AuthorizationData>()
                    //localAuthorizationList = new List<AuthorizationData>()
                    //{
                    //     new AuthorizationData()
                    //     {

                    //          idTagInfo=new IdTagInfo(){  expiryDate=DateTime.Now.ToUniversalTime().AddDays(3), status=  AuthorizationStatus.Accepted},
                    //           idTag="F5902677"
                    //     }, new AuthorizationData()
                    //     {
                    //          idTagInfo=new IdTagInfo(){  expiryDate=DateTime.Now.ToUniversalTime().AddDays(3), status=  AuthorizationStatus.Expired},
                    //           idTag="772690F5"
                    //     }
                    //}

                };

                //request.localAuthorizationList.Add(new AuthorizationData()
                //{
                //    idTag = "F5902677",
                //    idTagInfo = new IdTagInfo()
                //    {
                //        parentIdTag = "0000000000000000001",
                //        expiryDate = DateTime.UtcNow.AddMonths(1),
                //        status = AuthorizationStatus.ConcurrentTx
                //    }
                //});

                request.localAuthorizationList.Add(new AuthorizationData()
                {
                    idTag = "AA",
                    idTagInfo = new IdTagInfo()
                    {
                        parentIdTag = "SuperVisor",
                        expiryDate = DateTime.UtcNow.AddMinutes(5),
                        status = AuthorizationStatus.Accepted
                    }
                });

                request.localAuthorizationList.Add(new AuthorizationData()
                {
                    idTag = "BB",
                    idTagInfo = new IdTagInfo()
                    {
                        parentIdTag = "SuperVisor",
                        expiryDate = DateTime.UtcNow.AddMinutes(5),
                        status = AuthorizationStatus.Accepted
                    }
                });

                request.localAuthorizationList.Add(new AuthorizationData()
                {
                    idTag = "CC",
                    idTagInfo = new IdTagInfo()
                    {
                        parentIdTag = "SuperVisor",
                        expiryDate = DateTime.UtcNow.AddMinutes(5),
                        status = AuthorizationStatus.Accepted
                    }
                });

                request.localAuthorizationList.Add(new AuthorizationData()
                {
                    idTag = "DD",
                    idTagInfo = new IdTagInfo()
                    {
                        parentIdTag = "SuperVisor",
                        expiryDate = DateTime.UtcNow.AddMonths(-1),
                        status = AuthorizationStatus.Invalid
                    }
                });

                request.localAuthorizationList.Add(new AuthorizationData()
                {
                    idTag = "EE",
                    idTagInfo = new IdTagInfo()
                    {
                        parentIdTag = "SuperVisor",
                        expiryDate = DateTime.UtcNow.AddMonths(-1),
                        status = AuthorizationStatus.Invalid
                    }
                });

                for (int i = 0; i < size - request.localAuthorizationList.Count(); i++)
                {
                    request.localAuthorizationList.Add(new AuthorizationData()
                    {
                        idTag = DateTime.Now.ToString("yyyyMMddHHmmss" + i.ToString("00000")),
                        idTagInfo = new IdTagInfo()
                        {
                            parentIdTag = "0000000000000000001",
                            expiryDate = DateTime.UtcNow.AddMonths(1),
                            status = AuthorizationStatus.Accepted
                        }

                    });

                }


                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
        #endregion


        private void SetRemoteTrigger(string action)
        {
            try
            {
                string type = action.Split('_').Last();
                var uuid = Guid.NewGuid().ToString();
                var request = new TriggerMessageRequest()
                {
                    requestedMessage = (MessageTrigger)Enum.Parse(typeof(MessageTrigger), type, false)
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetGetConfiguration()
        {
            try
            {
                string uuid = Guid.NewGuid().ToString();
                var request = new GetConfigurationRequest()
                {
                    key = uxConfigKeyTb.Text.Split('/').ToList()
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void UxCmdCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            var item = uxCmdCb.SelectedValue as ComboBoxItem;
            action = item.Content as string;

        }


        private void SetRemoteStartTransaction(SetChargingProfileRequest csProfile = null)
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new RemoteStartTransactionRequest()
                {
                    connectorId = int.Parse(uxConnectorIdTb.Text),
                    idTag = uxIdTagTb.Text

                };
                if (csProfile != null)
                {
                    request.chargingProfile = csProfile.csChargingProfiles;
                }

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetUnlockConnector()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new UnlockConnectorRequest()
                {
                    connectorId = int.Parse(uxConnectorIdTb.Text),

                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetChangeAvailability_Inoperative()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ChangeAvailabilityRequest()
                {
                    connectorId = int.Parse(uxConnectorIdTb.Text),
                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Inoperative
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetChangeAvailability_Operative()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ChangeAvailabilityRequest()
                {
                    connectorId = int.Parse(uxConnectorIdTb.Text),
                    type = EVCB_OCPP.Packet.Messages.SubTypes.AvailabilityType.Operative
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }




        private void SetChangeConfiguration()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ChangeConfigurationRequest()
                {
                    key = uxConfigKeyTb.Text,
                    value = uxConfigValueTb.Text,

                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetClearCache()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ClearCacheRequest()
                {

                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }



        private void SetGetConfiguration_ALL()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new GetConfigurationRequest()
                {
                    key = new List<string>() { }
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }



        private void SetHardReset()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ResetRequest()
                {
                    type = EVCB_OCPP.Packet.Messages.SubTypes.ResetType.Hard
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetSoftReset()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new ResetRequest()
                {
                    type = EVCB_OCPP.Packet.Messages.SubTypes.ResetType.Soft
                };

                WritetoDB(uuid, request);
                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SetRemoteStopTransaction()
        {
            try
            {
                var uuid = Guid.NewGuid().ToString();
                var request = new RemoteStopTransactionRequest()
                {
                    transactionId = int.Parse(uxTransactionIdTb.Text)
                };

                WritetoDB(uuid, request);

                uxMsgTb.Text = string.Format("UUID:{0}", uuid);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }



        private void WritetoDB(string uuid, IRequest request, string action = "", string destroyData = "")
        {
            using (var db = new MainDBContext())
            {
                db.MachineOperateRecord.Add(new MachineOperateRecord()
                {
                    CreatedOn = DateTime.Now.ToUniversalTime(),
                    ChargeBoxId = uxChargeBoxIdTb.Text,
                    SerialNo = uuid,
                    RequestContent = !string.IsNullOrEmpty(destroyData) ? destroyData : JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                    EVSE_Status = 0,
                    Status = 0,
                    RequestType = 1,
                    Action = !string.IsNullOrEmpty(destroyData) ? action : request.Action.ToString()

                });

                db.ServerMessage.Add(new ServerMessage()
                {
                    ChargeBoxId = uxChargeBoxIdTb.Text,
                    CreatedBy = !string.IsNullOrEmpty(destroyData) ? "Destroyer" : "TestTool",
                    CreatedOn = DateTime.Now.ToUniversalTime(),
                    OutAction = !string.IsNullOrEmpty(destroyData) ? action : request.Action.ToString(),
                    OutRequest = !string.IsNullOrEmpty(destroyData) ? destroyData : JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                    SerialNo = uuid,
                    InMessage = string.Empty

                });

                db.SaveChanges();
            }
        }

        private void uxFileSubmitBtn_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "Select file";
            var result = openFileDialog.ShowDialog();
            if (result == true)
            {
                uxUploadFileTb.Text = openFileDialog.FileName;
            }
        }



        private void uxUploadBtn_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(uxUploadFileTb.Text))
            {
                uxMsgTb.Text = "Please select upload file!";
                return;
            }

            FileInfo f = new FileInfo(uxUploadFileTb.Text);

            int size = (int)f.Length;
            string md5 = "";
            string filePreUrl = ConfigurationManager.AppSettings["UpdateFWPreUrl"];
            using (WebClient client = new WebClient())
            {
                client.UseDefaultCredentials = false;
                client.Headers.Add("Content-Type", "application/octet-stream");
                using (Stream fileStream = File.OpenRead(uxUploadFileTb.Text))
                {
                    var _md5 = MD5.Create();
                    var hash = _md5.ComputeHash(fileStream);
                    md5 = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();

                }
            }

            UploadFile ufObj = new UploadFile();
            ufObj.CreatedOn = DateTime.Now.ToUniversalTime();
            ufObj.FileExtensionName = System.IO.Path.GetExtension(uxUploadFileTb.Text);
            ufObj.Id = Guid.NewGuid().ToString();
            ufObj.FileName = md5 + ufObj.FileExtensionName;
            ufObj.FilePath = "~/UploadFiles/Fw/" + ufObj.FileName;
            ufObj.FileSize = size;
            ufObj.FileMD5 = md5;
            ufObj.OriginName = System.IO.Path.GetFileName(uxUploadFileTb.Text);
            ufObj.FileUrl = new Uri(Properties.Settings.Default.UpdateFWPreUrl + ufObj.FilePath.Replace("~/", "")).ToString();
            ufObj.VendorId = "TestTool";
            ufObj.ModelName = "TestTool";
            ufObj.ModuleId = 0;

            using (var db = new MainDBContext())
            {
                db.UploadFile.Add(ufObj);
                db.SaveChanges();

            }

            string filePath = uxUploadFileTb.Text;
            uxMsgTb.Text = "Uploading........";

            Task.Run(async () =>
            {
                await UploadTask(filePath, ufObj.FileName);
            });










        }

        private async Task UploadTask(string filePath, string fileName)
        {

            bool uploadResult = UploadClient.FtpUploadBroken(filePath, @"ftp://ocpp.phihong.com.tw/" + fileName);

            await Dispatcher.BeginInvoke(new Action(() =>
            {
                if (uploadResult)
                {
                    uxMsgTb.Text = "Current Progress :100 %";
                    Thread.CurrentThread.Join(100);
                }
                uxMsgTb.Text = "Upload File Result :" + (uploadResult ? "Success" : "Fail");


            }));




        }

        private void UploadClient_OnUploadProgress(double percent)
        {
            Dispatcher.BeginInvoke(new Action(() =>
            {
                uxMsgTb.Text = "Current Progress :" + (int)percent + " %";

            }));
        }

        private void uxFTPUploadBtn_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(uxUploadFileTb.Text))
            {
                uxMsgTb.Text = "Please select upload file!";
                return;
            }

            FileInfo f = new FileInfo(uxUploadFileTb.Text);

            int size = (int)f.Length;
            string md5 = "";

            using (WebClient client = new WebClient())
            {
                client.UseDefaultCredentials = false;
                client.Headers.Add("Content-Type", "application/octet-stream");
                using (Stream fileStream = File.OpenRead(uxUploadFileTb.Text))
                {
                    var _md5 = MD5.Create();
                    var hash = _md5.ComputeHash(fileStream);
                    md5 = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant();

                }
            }

            UploadFile ufObj = new UploadFile();
            ufObj.CreatedOn = DateTime.Now.ToUniversalTime();
            ufObj.FileExtensionName = System.IO.Path.GetExtension(uxUploadFileTb.Text);
            ufObj.Id = Guid.NewGuid().ToString();
            ufObj.FileName = md5 + ufObj.FileExtensionName;
            ufObj.FilePath = "~/UploadFiles/Fw/" + ufObj.FileName;
            ufObj.FileSize = size;
            ufObj.FileMD5 = md5;
            ufObj.OriginName = System.IO.Path.GetFileName(uxUploadFileTb.Text);
            ufObj.FileUrl = new Uri(Properties.Settings.Default.FTPUpdateFWPreUrl + ufObj.FileName).ToString();
            ufObj.VendorId = "TestTool";
            ufObj.ModelName = "TestTool";
            ufObj.ModuleId = 0;

            using (var db = new MainDBContext())
            {
                db.UploadFile.Add(ufObj);
                db.SaveChanges();

            }



            string filePath = uxUploadFileTb.Text;
            uxMsgTb.Text = "Uploading........";

            Task.Run(async () =>
            {
                await UploadTask(filePath, ufObj.FileName);
            });


        }


        private void uxRefreshBtn_Click(object sender, RoutedEventArgs e)
        {
            using (var db = new MainDBContext())
            {
                publishes = db.UploadFile.OrderByDescending(c => c.CreatedOn).Take(20).ToList();

                StringBuilder sb = new StringBuilder();
                uxPublishCb.Items.Clear();
                foreach (var i in publishes)
                {
                    string prefix = i.FileUrl.StartsWith("ftp") ? "FTP" : "HTTP";
                    sb.Clear();
                    sb.Append(string.Format("[{0}]", prefix));
                    sb.Append("_上傳日期:");
                    sb.Append(i.CreatedOn.ToString());
                    sb.Append("_檔名:");
                    sb.Append(i.OriginName);

                    uxPublishCb.Items.Add(sb.ToString());
                    uxPublishCb.SelectedIndex = 0;
                }
            }

        }

        private void uxPublishBtn_Click(object sender, RoutedEventArgs e)
        {
            if (selectedPublish < 0)
            {
                uxMsgTb.Text = "Please choose publish version!";
                return;
            }
            using (var db = new MainDBContext())
            {

                var machine = db.Machine.Where(x => x.ChargeBoxId == uxChargeBoxIdTb.Text).FirstOrDefault();
                MachineVersionFile obj = new MachineVersionFile()
                {
                    ChargeBoxId = uxChargeBoxIdTb.Text,
                    UploadFileId = publishes[selectedPublish].Id,
                    CreatedOn = DateTime.Now.ToUniversalTime()
                };

                db.MachineVersionFile.Add(obj);

                //將machine的軟體更新更新到這個值
                db.SaveChanges();

                machine.FW_AssignedVersion = obj.Id;

                db.SaveChanges();


            }
            uxMsgTb.Text = "Publish Complete";


        }

        private void uxPublishCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            selectedPublish = uxPublishCb.SelectedIndex;

        }

        private void uxClearPublishBtn_Click(object sender, RoutedEventArgs e)
        {
            using (var db = new MainDBContext())
            {

                var machine = db.Machine.Where(x => x.ChargeBoxId == uxChargeBoxIdTb.Text).FirstOrDefault();
                machine.FW_AssignedVersion = null;
                db.SaveChanges();
            }

            uxMsgTb.Text = "Clear Publish";

        }

        private void uxChargeBoxIdTb_LostFocus(object sender, RoutedEventArgs e)
        {
            Properties.Settings.Default.ChargeBoxId = uxChargeBoxIdTb.Text;
            Properties.Settings.Default.Save();

        }


        private string GetDestroyVersionData(string action)
        {
            string result = "";
            try
            {
                string path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, action + ".json");
                var request = JsonConvert.DeserializeObject(File.ReadAllText(path));
                result = JsonConvert.SerializeObject(request);
            }
            catch (Exception ex)
            {
                uxMsgTb.Text += "解析檔案發生問題 " + ex.ToString();
            }

            return result;
        }

        private void uxDestroyCb_Checked(object sender, RoutedEventArgs e)
        {
            isDestroyMode = true;
            uxConnectorIdTb.IsEnabled = false;
            uxReservationTb.IsEnabled = false;
            uxIdTagTb.IsEnabled = false;
            uxParentIdTagTb.IsEnabled = false;
            uxTransactionIdTb.IsEnabled = false;
            uxLocalListSizeTb.IsEnabled = false;
            uxConfigKeyTb.IsEnabled = false;
            uxConfigValueTb.IsEnabled = false;
            uxExpiryTimeTb.IsEnabled = false;
        }

        private void uxDestroyCb_Unchecked(object sender, RoutedEventArgs e)
        {
            isDestroyMode = false;
            uxConnectorIdTb.IsEnabled = true;
            uxReservationTb.IsEnabled = true;
            uxIdTagTb.IsEnabled = true;
            uxParentIdTagTb.IsEnabled = true;
            uxTransactionIdTb.IsEnabled = true;
            uxLocalListSizeTb.IsEnabled = true;
            uxConfigKeyTb.IsEnabled = true;
            uxConfigValueTb.IsEnabled = true;
            uxExpiryTimeTb.IsEnabled = true;
        }
    }
}
