using AutoMapper;
using Edge.Core.Database;
using Edge.Core.Database.Models;
using Edge.Core.IndustryStandardInterface.Pump;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Wayne.FDCPOSLibrary;
namespace EagleStar_Pump
{
public class PumpHandler : IFdcPumpController, IDisposable
{
private PumpGroupConfiguration appConfig;
private ILogger logger;
private IServiceProvider services;
private System.Timers.Timer autoCallingTimer;
private string owner = "EagleStarPumpApp";
private string type = "YingGaoFlag";
///
///
///
public PumpHandler(PumpGroupConfiguration appConfig, ILogger logger, IServiceProvider services)
{
this.appConfig = appConfig;
this.logger = logger;
this.services = services;
int fid = 0;
var genericDatas = GetGenericData(type);
if (genericDatas.Count() > 0)
{
fid = (int)genericDatas.First().IntProperty0;
}
else
{
_ = SaveDbAsync(type, new GenericData()
{
Type = type,
IntProperty0 = fid
});
}
this.autoCallingTimer = new System.Timers.Timer(3000);
this.autoCallingTimer.Elapsed += (_, __) =>
{
this.autoCallingTimer?.Stop();
var dataList = SqlClientHelper.ReadTransactionData(this.appConfig, this.logger, ref fid);
foreach (var trx in dataList)
{
this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(trx));
}
_ = UpdateDbAsync(type, new GenericData()
{
Type = type,
IntProperty0 = fid
});
this.autoCallingTimer?.Start();
};
this.autoCallingTimer?.Start();
}
private IEnumerable GetGenericData(string type)
{
using (var scope = this.services.CreateScope())
{
var objMapper = this.services.GetRequiredService();
var dbContext = scope.ServiceProvider.GetRequiredService();
var genericDatas = dbContext.GenericDatas.Where(gd =>
gd.Type == type
&& gd.Owner == owner);
return objMapper.Map>(genericDatas.ToList());
}
}
private async Task SaveDbAsync(string type, GenericData data)
{
using (var scope = this.services.CreateScope())
{
try
{
var dbContext = scope.ServiceProvider.GetRequiredService();
data.Owner = owner;
dbContext.GenericDatas.Add(data);
await dbContext.SaveChangesAsync();
}
catch (Exception ex)
{
logger.LogError($"In SaveOrUpdateDbAsync: {ex}");
}
}
}
private async Task UpdateDbAsync(string type, GenericData data)
{
using (var scope = this.services.CreateScope())
{
try
{
var dbContext = scope.ServiceProvider.GetRequiredService();
var genericDatas = dbContext.GenericDatas.Where(gd =>
gd.Type == type
&& gd.Owner == owner);
if (genericDatas.Count() > 0)
{
var gdt = genericDatas.First();
gdt.IntProperty0 = data.IntProperty0;
dbContext.GenericDatas.Update(gdt);
await dbContext.SaveChangesAsync();
}
}
catch (Exception ex)
{
logger.LogError($"In SaveOrUpdateDbAsync: {ex}");
}
}
}
private IEnumerable nozzles = new List();
private bool enableFuelSimulation;
private int pumpId;
private int pumpPhysicalId;
private LogicalDeviceState currentState = LogicalDeviceState.FDC_READY;
public string Name => "Bogus_Pump handler";
public int PumpId => this.pumpId;
public int PumpPhysicalId => this.pumpPhysicalId;
public IEnumerable Nozzles => this.nozzles;
public int AmountDecimalDigits => 2;
public int VolumeDecimalDigits => 2;
public int PriceDecimalDigits => 2;
public int VolumeTotalizerDecimalDigits => 2;
public event EventHandler OnStateChange;
public event EventHandler OnCurrentFuellingStatusChange;
public async Task AuthorizeAsync(byte logicalNozzleId)
{
//if (this.enableFuelSimulation)
// return false;
if (this.currentState == LogicalDeviceState.FDC_AUTHORISED
|| this.currentState == LogicalDeviceState.FDC_FUELLING)
return false;
LogicalNozzle n = this.nozzles.FirstOrDefault(n => n.LogicalId == logicalNozzleId);
if (n == null) return await Task.FromResult(false);
await Task.Delay(1000);
this.currentState = LogicalDeviceState.FDC_AUTHORISED;
this.OnStateChange?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(this.currentState, n));
await Task.Delay(1000);
this.currentState = LogicalDeviceState.FDC_FUELLING;
this.OnStateChange?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(this.currentState, n));
await Task.Delay(300);
_ = Task.Run(() =>
{
int amt = 0;
int vol = 0;
int seqNumber = (int)(DateTime.Now.Subtract(new DateTime(2021, 1, 1)).TotalSeconds);
const int FireMaxTimes = 12;
int firedTimes = 0;
while (true)
{
amt += new Random().Next(500, 1000);
vol += new Random().Next(100, 300);
this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
{
Amount = amt,
Volumn = vol,
Nozzle = n,
Price = n.RealPriceOnPhysicalPump ?? -1,
SequenceNumberGeneratedOnPhysicalPump = seqNumber,
Finished = false
}));
Thread.Sleep(1000);
firedTimes++;
if (firedTimes > FireMaxTimes)
{
this.currentState = LogicalDeviceState.FDC_READY;
this.OnStateChange?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(this.currentState, n));
this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
{
Amount = amt,
Volumn = vol,
Nozzle = n,
Price = n.RealPriceOnPhysicalPump ?? -1,
SequenceNumberGeneratedOnPhysicalPump = seqNumber,
AmountTotalizer = new Random().Next(9999, 99999999),
VolumeTotalizer = new Random().Next(1000, 11999999),
Finished = true
}));
break;
}
}
});
return await Task.FromResult(true);
}
public Task AuthorizeWithAmountAsync(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId)
{
return this.AuthorizeAsync(logicalNozzleId);
}
public Task AuthorizeWithVolumeAsync(int volumnWithoutDecimalPoint, byte logicalNozzleId)
{
return this.AuthorizeAsync(logicalNozzleId);
}
public Task ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
{
if (this.enableFuelSimulation)
return Task.FromResult(false);
var targetNozzle = this.nozzles.FirstOrDefault(n => n.LogicalId == logicalNozzleId);
if (targetNozzle != null)
{
targetNozzle.RealPriceOnPhysicalPump = newPriceWithoutDecimalPoint;
targetNozzle.ExpectingPriceOnFcSide = newPriceWithoutDecimalPoint;
return Task.FromResult(true);
}
else
return Task.FromResult(false);
}
public Task FuelingRoundUpByAmountAsync(int amount)
{
return Task.FromResult(true);
}
public Task FuelingRoundUpByVolumeAsync(int volume)
{
return Task.FromResult(true);
}
public Task LockNozzleAsync(byte logicalNozzleId)
{
return Task.FromResult(true);
}
public void OnFdcServerInit(Dictionary parameters)
{
if (parameters.ContainsKey("LastPriceChange"))
{
// nozzle logical id:rawPrice
var lastPriceChanges = parameters["LastPriceChange"] as Dictionary;
foreach (var priceChange in lastPriceChanges)
{
var targetNozzle = this.nozzles.FirstOrDefault(n => n.LogicalId == priceChange.Key);
if (targetNozzle != null)
{
targetNozzle.RealPriceOnPhysicalPump = priceChange.Value;
targetNozzle.ExpectingPriceOnFcSide = priceChange.Value;
}
}
}
}
public Task QueryStatusAsync()
{
return Task.FromResult(this.currentState);
}
public Task> QueryTotalizerAsync(byte logicalNozzleId)
{
if (this.enableFuelSimulation)
Task.FromResult(new Tuple(-1, -1));
return Task.FromResult(
new Tuple(
new Random().Next(100000, 999999),
new Random().Next(50000, 99999)));
}
public Task ResumeFuellingAsync()
{
return Task.FromResult(true);
}
public Task SuspendFuellingAsync()
{
return Task.FromResult(true);
}
public Task UnAuthorizeAsync(byte logicalNozzleId)
{
return Task.FromResult(true);
}
public Task UnlockNozzleAsync(byte logicalNozzleId)
{
return Task.FromResult(true);
}
public void Dispose()
{
this.autoCallingTimer?.Dispose();
}
internal void DrivenPumpStateTo(byte? logicalNozzleId, LogicalDeviceState pumpNewState,
int? amountWithoutDecimalPoint, int? volumeWithoutDecimalPoint, int? priceWithoutDecimalPoint)
{
var targetNozzle = this.nozzles?.FirstOrDefault(n => n.LogicalId == logicalNozzleId);
if (pumpNewState == LogicalDeviceState.FDC_FUELLING)
{
this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
{
Amount = amountWithoutDecimalPoint ?? 0,
Volumn = volumeWithoutDecimalPoint ?? 0,
Nozzle = targetNozzle,
Price = priceWithoutDecimalPoint ?? 0,
//SequenceNumberGeneratedOnPhysicalPump = seqNumber,
Finished = false
}));
}
if (this.currentState == pumpNewState) return;
this.currentState = pumpNewState;
this.OnStateChange?.Invoke(this,
new FdcPumpControllerOnStateChangeEventArg(this.currentState, targetNozzle));
}
internal void DrivenPumpRaiseNewTrx(byte? logicalNozzleId,
int amountWithoutDecimalPoint, int volumeWithoutDecimalPoint, int priceWithoutDecimalPoint, int trxSeqNumber)
{
var targetNozzle = this.nozzles?.FirstOrDefault(n => n.LogicalId == logicalNozzleId);
this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
{
Amount = amountWithoutDecimalPoint,
Volumn = volumeWithoutDecimalPoint,
Nozzle = targetNozzle,
Price = priceWithoutDecimalPoint,
SequenceNumberGeneratedOnPhysicalPump = trxSeqNumber,
Finished = true
}));
}
}
}