using EVCB_OCPP.Packet.Messages.Basic;
using EVCB_OCPP.WSServer.Dto;
using log4net.Core;
using Microsoft.Extensions.Logging;

namespace EVCB_OCPP.WSServer.Service.WsService;

public class WsClientData : WsSession
{ /// <summary>
  /// 根據unique id來儲存.取出OCPP Request
  /// </summary>
    public Queue queue = new Queue();

    public EVCB_OCPP20.Packet.Messages.Basic.Queue queue20 = new EVCB_OCPP20.Packet.Messages.Basic.Queue();

    public bool? IsPending { set; get; }
    public bool IsCheckIn { set; get; } = false;

    public string ChargeBoxId { set; get; }

    public Guid CustomerId { get; set; }

    public string MachineId { set; get; }

    public bool ISOCPP20 { set; get; }

    public bool ResetSecurityProfile { set; get; }


    public bool IsAC { set; get; } = true;

    #region Billing

    public Dictionary<string, string> UserPrices { set; get; } = new Dictionary<string, string>();

    public Dictionary<string, string> UserDisplayPrices { set; get; } = new Dictionary<string, string>();

    public List<ChargingPrice> ChargingPrices { set; get; }

    /// <summary>
    /// 電樁顯示費率
    /// </summary>
    public string DisplayPrice { set; get; }

    /// <summary>
    /// 充電費率 以小時計費
    /// </summary>
    public decimal ChargingFeebyHour { set; get; }

    /// <summary>
    /// 停車費率 以小時計費
    /// </summary>
    public decimal ParkingFee { set; get; }

    /// <summary>
    /// 電樁是否計費
    /// </summary>
    public bool IsBilling { set; get; }

    /// <summary>
    /// 收費方式 1: 以度計費 2:以小時計費
    /// </summary>
    public int BillingMethod { set; get; }


    /// <summary>
    /// 電樁適用幣別
    /// </summary>
    public string Currency { get; internal set; }

    #endregion

    public string CustomerName { get; set; }

    public string StationId { set; get; }

    public event EventHandler<string> m_ReceiveData;

    private string stringBuffer = string.Empty;
    private readonly ILogger<WsClientData> logger;

    public WsClientData(ILogger<WsClientData> logger) : base(logger)
    {
        ChargeBoxId = SessionID;
        MachineId = SessionID;
        this.logger = logger;
    }

    internal override void HandleReceivedData(string data)
    {
        stringBuffer += data;
        //logger.LogInformation("{StringBuffer}", stringBuffer);
        while (TryGetOCPPMsg(ref stringBuffer, out var msg))
        {
            m_ReceiveData?.Invoke(this, msg);
        }
    }

    private bool TryGetOCPPMsg(ref string buffer, out string msg)
    {
        msg = string.Empty;
        int? startIndex = null;
        int? stopIndex = null;
        uint cnt = 0;

        for (int index = 0; index < buffer.Length; index++)
        {
            if (buffer[index] == '[')
            {
                cnt++;
                if (startIndex == null)
                {
                    startIndex = index;
                }
            }

            if (startIndex != null && buffer[index] == ']')
            {
                cnt--;
            }

            if (startIndex != null && cnt == 0)
            {
                stopIndex = index;
                break;
            }
        }

        if (startIndex is not null && stopIndex is not null)
        {
            msg = buffer.Substring(startIndex.Value, stopIndex.Value - startIndex.Value);
            buffer = buffer.Substring(stopIndex.Value + 1);
            return true;
        }

        return false;
    }
}