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.FirmwareManagement;
using Newtonsoft.Json;
using OCPPServer.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace EVCB_OCPP.WSServer.Message
{
    internal partial class ProfileHandler
    {
        internal MessageResult ExecuteFirmwareManagementRequest(Actions action, ClientData session, IRequest request)
        {
            MessageResult result = new MessageResult() { Success = false };

            switch (action)
            {

                case Actions.FirmwareStatusNotification:
                    {
                        FirmwareStatusNotificationRequest _request = request as FirmwareStatusNotificationRequest;

                        if (_request.status == Packet.Messages.SubTypes.FirmwareStatus.Idle)
                        {
                            string requestId = Guid.NewGuid().ToString();
                            using (var db = new MainDBContext())
                            {
                                var machine = db.Machine.Where(x => x.FW_AssignedMachineVersionId.HasValue == true &&
                                    x.FW_AssignedMachineVersionId != x.FW_VersionReport && x.ChargeBoxId == session.ChargeBoxId)
                                    .Select(x => new { x.Id, x.FW_AssignedMachineVersionId }).AsNoTracking().FirstOrDefault();

                                if (machine != null)
                                {
                                    var mv = db.MachineVersion.Include(c => c.PublishVersion)
                                     .Include(c => c.PublishVersion.PublishVersionFiles)
                                     .Include(c => c.PublishVersion.PublishVersionFiles.Select(z => z.UploadFile))
                                     .Where(c => c.Id == machine.FW_AssignedMachineVersionId.Value).First();

                                    string downloadUrl = mv.PublishVersion.PublishVersionFiles.FirstOrDefault().UploadFile.FileUrl;

                                    var _updateFWrequest = new UpdateFirmwareRequest()
                                    {
                                        location = new Uri(downloadUrl),
                                        retries = 3,
                                        retrieveDate = DateTime.Now,
                                        retryInterval = 10
                                    };
                                    db.MachineOperateRecord.Add(new MachineOperateRecord()
                                    {
                                        CreatedOn = DateTime.Now,
                                        ChargeBoxId = session.ChargeBoxId,
                                        SerialNo = requestId,
                                        RequestContent = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                                        EVSE_Status = 0,
                                        EVSE_Value = "Fw Version:" + machine.FW_AssignedMachineVersionId,
                                        Status = 0,
                                        RequestType = 0,

                                    });

                                    db.ServerMessage.Add(new ServerMessage()
                                    {
                                        ChargeBoxId = session.ChargeBoxId,
                                        CreatedBy = "Server",
                                        CreatedOn = DateTime.Now,
                                        OutAction = _updateFWrequest.Action.ToString(),
                                        OutRequest = JsonConvert.SerializeObject(_updateFWrequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None }),
                                        SerialNo = requestId,
                                        InMessage = string.Empty

                                    });

                                    db.SaveChanges();

                                }

                            }
                        }
                        else
                        {
                            using (var db = new MainDBContext())
                            {
                                var item = db.MachineOperateRecord.Where(x => x.ChargeBoxId == session.ChargeBoxId && x.RequestType == 0)
                                    .OrderByDescending(x => x.CreatedOn).FirstOrDefault();

                                item.EVSE_Status = (int)_request.status;
                                item.FinishedOn = DateTime.Now;

                                if (!string.IsNullOrEmpty(item.EVSE_Value) && _request.status == Packet.Messages.SubTypes.FirmwareStatus.Installed)
                                {
                                    int version = 0;
                                    int.TryParse(item.EVSE_Value.Split(':').Last(), out version);
                                    var machine = db.Machine.Where(x => x.ChargeBoxId == session.ChargeBoxId).FirstOrDefault();
                                    machine.FW_VersionReport = version;
                                }

                                db.SaveChanges();
                            }
                        }

                        var confirm = new FirmwareStatusNotificationConfirmation() { };

                        result.Message = confirm;
                        result.Success = true;
                    }
                    break;
                case Actions.DiagnosticsStatusNotification:
                    {
                        DiagnosticsStatusNotificationRequest _request = request as DiagnosticsStatusNotificationRequest;

                        var confirm = new DiagnosticsStatusNotificationConfirmation() { };

                        result.Message = confirm;
                        result.Success = true;

                    }
                    break;

                default:
                    {
                        Console.WriteLine(string.Format("Not Implement {0} Logic", request.GetType().ToString().Replace("OCPPPackage.Messages.FirmwareManagement.", "")));
                    }
                    break;
            }
            return result;
        }

        internal MessageResult ExecuteFirmwareManagementConfirm(Actions action, ClientData session, IConfirmation confirm, string requestId)
        {
            MessageResult result = new MessageResult() { Success = true };

            switch (action)
            {
                case Actions.UpdateFirmware:
                case Actions.GetDiagnostics:
                    {
                        using (var db = new MainDBContext())
                        {
                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.Now;
                                operation.Status = 1;//電樁有回覆
                                operation.EVSE_Status = (int)1;//OK
                                db.SaveChanges();
                            }

                        }
                    }
                    break;
                default:
                    {
                        Console.WriteLine(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.FirmwareManagement.", "")));
                    }
                    break;
            }
            return result;
        }


        internal MessageResult ReceivedFirmwareManagementError(Actions action, string errorMsg, ClientData session, string requestId)
        {
            MessageResult result = new MessageResult() { Success = true };

            switch (action)
            {
                case Actions.FirmwareStatusNotification:
                case Actions.UpdateFirmware:
                case Actions.GetDiagnostics:
                case Actions.DiagnosticsStatusNotification:
                    {
                        using (var db = new MainDBContext())
                        {
                            var operation = db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefault();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.Now;
                                operation.Status = 1;//電樁有回覆
                                operation.EVSE_Status = (int)255;//錯誤
                                operation.EVSE_Value = errorMsg;
                                db.SaveChanges();
                            }

                        }
                    }
                    break;

                default:
                    {
                        Console.WriteLine(string.Format("Not Implement {0} Logic", action));
                    }
                    break;
            }
            return result;

        }
    }
}