using Edge.Core.IndustryStandardInterface.Pump;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Edge.Core.Database.Models
{
    public enum FuelSaleTransactionState
    {
        Undefined = 0,
        Payable = 1,
        Locked = 2,
        Paid = 3,
        Cleared = 4,
    }

    public class FuelSaleTransaction
    {
        // FDC defined:
        //SALE_TRX_UNDEFINED = 0,
        //SALE_TRX_PAYABLE = 1,
        //SALE_TRX_LOCKED = 2,
        //SALE_TRX_PAID = 3,
        //SALE_TRX_CLEARED = 4,


        /// <summary>
        /// Gets or sets the release token for this trx, release token is an database unique
        /// id for a trx, unlike `TransactionSeqNumberFromPhysicalPump`, it's a 
        /// device dependent and will be re-cyclely used by device, so there're may have multiple 
        /// trx in database with same `TransactionSeqNumberFromPhysicalPump`, but release token is
        /// guranteed to be unique for a trx.
        /// </summary>
        [Key]
        public int ReleaseToken { get; set; }
        public int PumpId { get; set; }
        public int LogicalNozzleId { get; set; }
        public string TransactionSeqNumberFromPhysicalPump { get; set; }
        public FuelSaleTransactionState State { get; set; }

        public string ProductBarcode { get; set; }

        /// <summary>
        /// without decimal points
        /// </summary>
        public int UnitPrice { get; set; }

        /// <summary>
        /// without decimal points
        /// </summary>
        public int Amount { get; set; }

        /// <summary>
        /// without decimal points
        /// </summary>
        public int Volumn { get; set; }

        /// <summary>
        /// Gets or sets the Fdc Client WorkStationId which reserved this fuel point.
        /// the Pos id is the workstation id parameter used in Fdc client connect to Fdc server, each client
        /// should have an unique this id to distinguish from each other.
        /// until 2017 Dec, the pos id is config in COS (web), model: SiteDevice , column: PosDeviceFdcClientId, once the android POS
        /// downloaded this value via AccessToken web service, it will be deducted with 100, and then plus 110, like you config the id in
        /// COS is 109, then in fdc client connection, the final value will be 119.
        /// </summary>
        public string LockedByFdcClientId { get; set; }
        public DateTime? LockedTime { get; set; }

        public string AuthorizedByFdcClientId { get; set; }
        public DateTime? AuthorizedTime { get; set; }

        public string PaidByFdcClientId { get; set; }
        public DateTime? PaidTime { get; set; }

        public DateTime? SaleStartTime { get; set; }
        public DateTime? SaleEndTime { get; set; }

        /// <summary>
        /// the money amount totalizer value after this new trx done, without decimal points
        /// </summary>
        public int AmountTotalizer { get; set; }

        /// <summary>
        /// the volume amount totalizer value after this new trx done, without decimal points
        /// </summary>
        public int VolumeTotalizer { get; set; }

        public override string ToString()
        {
            return $"ReleaseToken: {ReleaseToken }, PumpId: {PumpId }, logicalNozzleId: {LogicalNozzleId }, " +
                $"seqNo: { (TransactionSeqNumberFromPhysicalPump ?? "")}, state: {State }, amount: {Amount }, " +
                $"LockedByFdcClientId: { (LockedByFdcClientId ?? "")}, LockedTime: {(LockedTime?.ToShortTimeString() ?? "") }, " +
                $"AuthorizedByFdcClientId: { (AuthorizedByFdcClientId ?? "")}, PaidByFdcClientId: { (PaidByFdcClientId ?? "")}, " +
                $"SaleEndTime: {SaleEndTime?.ToString("yyyy-MM-dd HH:mm:ss fff") ?? ""}";
        }
    }

    public class FuelSaleTransactionResponse
    {
        // FDC defined:
        //SALE_TRX_UNDEFINED = 0,
        //SALE_TRX_PAYABLE = 1,
        //SALE_TRX_LOCKED = 2,
        //SALE_TRX_PAID = 3,
        //SALE_TRX_CLEARED = 4,

        private FuelSaleTransactionResponse(FuelSaleTransaction fuelSaleTransaction,
            IFdcPumpController fdcPumpController)
        {
            ReleaseToken = fuelSaleTransaction.ReleaseToken;
            PumpId = fuelSaleTransaction.PumpId;
            LogicalNozzleId = fuelSaleTransaction.LogicalNozzleId;
            TransactionSeqNumberFromPhysicalPump = fuelSaleTransaction.TransactionSeqNumberFromPhysicalPump;
            State = fuelSaleTransaction.State;
            ProductBarcode = fuelSaleTransaction.ProductBarcode;
            UnitPrice = (decimal)(fuelSaleTransaction.UnitPrice / Math.Pow(10, fdcPumpController.PriceDecimalDigits));
            Amount = (decimal)(fuelSaleTransaction.Amount / Math.Pow(10, fdcPumpController.AmountDecimalDigits));
            Volumn = (decimal)(fuelSaleTransaction.Volumn / Math.Pow(10, fdcPumpController.VolumeDecimalDigits));
            LockedByFdcClientId = fuelSaleTransaction.LockedByFdcClientId;
            LockedTime = fuelSaleTransaction.LockedTime;
            AuthorizedByFdcClientId = fuelSaleTransaction.AuthorizedByFdcClientId;
            AuthorizedTime = fuelSaleTransaction.AuthorizedTime;
            PaidTime = fuelSaleTransaction.PaidTime;
            SaleStartTime = fuelSaleTransaction.SaleStartTime;
            SaleEndTime = fuelSaleTransaction.SaleEndTime;
            AmountTotalizer = (decimal)(fuelSaleTransaction.AmountTotalizer / Math.Pow(10, fdcPumpController.AmountDecimalDigits));
            VolumeTotalizer = (decimal)(fuelSaleTransaction.VolumeTotalizer / Math.Pow(10, fdcPumpController.VolumeTotalizerDecimalDigits));
        }

        public static FuelSaleTransactionResponse CreateInstance(FuelSaleTransaction fuelSaleTransaction,
            IFdcPumpController fdcPumpController)
        {
            return new FuelSaleTransactionResponse(fuelSaleTransaction, fdcPumpController);
        }


        /// <summary>
        /// Gets or sets the release token for this trx, release token is an database unique
        /// id for a trx, unlike `TransactionSeqNumberFromPhysicalPump`, it's a 
        /// device dependent and will be re-cyclely used by device, so there're may have multiple 
        /// trx in database with same `TransactionSeqNumberFromPhysicalPump`, but release token is
        /// guranteed to be unique for a trx.
        /// </summary>
        [Key]
        public int ReleaseToken { get; set; }
        public int PumpId { get; set; }
        public int LogicalNozzleId { get; set; }
        public string TransactionSeqNumberFromPhysicalPump { get; set; }
        public FuelSaleTransactionState State { get; set; }

        public string ProductBarcode { get; set; }
        /// <summary>
        /// without decimal points
        /// </summary>
        public decimal UnitPrice { get; set; }

        /// <summary>
        /// without decimal points
        /// </summary>
        public decimal Amount { get; set; }

        /// <summary>
        /// without decimal points
        /// </summary>
        public decimal Volumn { get; set; }

        /// <summary>
        /// Gets or sets the Fdc Client WorkStationId which reserved this fuel point.
        /// the Pos id is the workstation id parameter used in Fdc client connect to Fdc server, each client
        /// should have an unique this id to distinguish from each other.
        /// until 2017 Dec, the pos id is config in COS (web), model: SiteDevice , column: PosDeviceFdcClientId, once the android POS
        /// downloaded this value via AccessToken web service, it will be deducted with 100, and then plus 110, like you config the id in
        /// COS is 109, then in fdc client connection, the final value will be 119.
        /// </summary>
        public string LockedByFdcClientId { get; set; }
        public DateTime? LockedTime { get; set; }

        public string AuthorizedByFdcClientId { get; set; }
        public DateTime? AuthorizedTime { get; set; }

        public string PaidByFdcClientId { get; set; }
        public DateTime? PaidTime { get; set; }

        public DateTime? SaleStartTime { get; set; }
        public DateTime? SaleEndTime { get; set; }

        /// <summary>
        /// the money amount totalizer value after this new trx done, without decimal points
        /// </summary>
        public decimal AmountTotalizer { get; set; }

        /// <summary>
        /// the volume amount totalizer value after this new trx done, without decimal points
        /// </summary>
        public decimal VolumeTotalizer { get; set; }

        public override string ToString()
        {
            return "ReleaseToken: " + ReleaseToken + ", PumpId: " + PumpId + ", logicalNozzleId: " + LogicalNozzleId + ", seqNo: " + (TransactionSeqNumberFromPhysicalPump ?? "")
                + ", state: " + State + ", amount: " + Amount + ", LockedByFdcClientId: " + (LockedByFdcClientId ?? "")
                + "LockedTime: " + (LockedTime?.ToShortTimeString() ?? "") + ", AuthorizedByFdcClientId: " + (AuthorizedByFdcClientId ?? "")
                + ", PaidByFdcClientId: " + (PaidByFdcClientId ?? "");
        }
    }
}
