using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace BulkPrinting
{
    public class SavedSettings {
        [JsonProperty("vendorId")]
        public int VendorId { get; set; }

        [JsonProperty("userId")]
        public int UserId { get; set; }

        [JsonProperty("username")]
        public string Username { get; set; }
    }

    public enum SessionModes {
        Invalid = 0,
        Offline = 1,
        Online = 2
    }

    public class MaxException
    {
        [JsonProperty("code")]
        public int? Code { get; set; }

        [JsonProperty("error")]
        public string Error { get; set; }
    }


    public class LoginData
    {
        [JsonProperty("vendorId")]
        public int VendorId { get; set; }

        [JsonProperty("serialNumber")]
        public string SerialNumber { get; set; }

        [JsonProperty("userId")]
        public int UserId { get; set; }

        [JsonProperty("username")]
        public string Username { get; set; }

        [JsonProperty("password")]
        public string Password
        {
            get
            {
                if (SecurePassword != null)
                {
                    IntPtr valuePtr = IntPtr.Zero;
                    try
                    {
                        valuePtr = Marshal.SecureStringToGlobalAllocUnicode(SecurePassword);
                        return Marshal.PtrToStringUni(valuePtr);
                    }
                    finally
                    {
                        Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
                    }
                }
                return null;
            }
        }

        public SecureString SecurePassword;
    }

    public class OrderPlacementData
    {
        [JsonProperty("productId")]
        public int ProductId { get; set; }

        [JsonProperty("quantity")]
        public int Quantity { get; set; }

        [JsonProperty("customerReference")]
        public string CustomerReference { get; set; }

        [JsonProperty("internalReference")]
        public string InternalReference { get; set; }
    }

    public class Warehouse
    {
        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }
    }

    public enum AccountStatus
    {
        Unknown,
        Enabled,
        Suspended,
        Closed
    }

    public class Account
    {
        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("status")]
        public AccountStatus Status { get; set; }

        [JsonProperty("reference")]
        public string Reference { get; set; }

        [JsonProperty("warehouse")]
        public Warehouse Warehouse { get; set; }

        [JsonProperty("balance")]
        public decimal Balance { get; set; }
    }

    public class Vendor
    {
        [JsonProperty("Id")]
        public int id { get; set; }

        [JsonProperty("SerialNumber")]
        public string serialNumber { get; set; }

        [JsonProperty("AccountId")]
        public int accountId { get; set; }
    }

    public enum UserLevel
    {
        Unknown = 0,
        Administrator = 4,
        CustomUser = 6
    }

    public class User
    {
        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("username")]
        public string Username { get; set; }

        [JsonProperty("firstName")]
        public string FirstName { get; set; }

        [JsonProperty("surname")]
        public string Surname { get; set; }

        [JsonProperty("account")]
        public Account Account { get; set; }

        [JsonProperty("enabled")]
        public bool Enabled { get; set; }

        [JsonProperty("level")]
        public int Level { get; set; }

        [JsonProperty("system")]
        public int System { get; set; }

        [JsonProperty("lastLogin")]
        public DateTime LastLogin { get; set; }

        [JsonProperty("canPrintOnline")]
        public bool CanPrintOnline { get; set; }

        [JsonProperty("onlinePrintValue")]
        public decimal OnlinePrintValue { get; set; }

        [JsonProperty("canReprintOnline")]
        public bool CanReprintOnline { get; set; }

        [JsonProperty("onlineReprintValue")]
        public decimal OnlineReprintValue { get; set; }

        [JsonProperty("canPrintOffline")]
        public bool CanPrintOffline { get; set; }

        [JsonProperty("offlinePrintValue")]
        public decimal OfflinePrintValue { get; set; }

        [JsonProperty("canReprintOffline")]
        public bool CanReprintOffline { get; set; }

        [JsonProperty("offlineReprintValue")]
        public decimal OfflineReprintValue { get; set; }

        [JsonProperty("bulkExport")]
        public bool BulkExport { get; set; }

        [JsonProperty("bulkReExport")]
        public bool BulkReExport { get; set; }

        [JsonProperty("bulkExportMaxValue")]
        public decimal BulkExportMaxValue { get; set; }

        [JsonProperty("bulkOrder")]
        public bool BulkOrder { get; set; }

        [JsonProperty("bulkOrderMaxValue")]
        public decimal BulkOrderMaxValue { get; set; }

        [JsonProperty("bulkViewPins")]
        public bool BulkViewPins { get; set; }
    }

    public class Payload
    {

        [JsonProperty("date")]
        public DateTime Date { get; set; }

        [JsonProperty("nonce")]
        public string Nonce { get; set; }

        [JsonProperty("user")]
        public User User { get; set; }

        [JsonProperty("vendor")]
        public Vendor Vendor { get; set; }

        [JsonProperty("encryptedDatabasePassword")]
        public byte[] EncryptedDatabasePassword { get; set; }

        [JsonProperty("encryptedVoucherKey")]
        public byte[] EncryptedVoucherKey { get; set; }
    }

    public class Credentials
    {
        public string responsePayload;

        [JsonProperty("payload")]
        public string payloadBase64
        {
            get
            {
                return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Globals.SessionData.Credentials.Payload)));
            }
            set
            {
                this.responsePayload = value;
                this.Payload = JsonConvert.DeserializeObject<Payload>(Encoding.UTF8.GetString(Convert.FromBase64String(value)));
            }
        }

        [JsonIgnore]
        public Payload Payload { get; set; }

        [JsonProperty("salt")]
        public byte[] Salt { get; set; }

        [JsonProperty("iterations")]
        public int Iterations { get; set; }

        [JsonProperty("signature")]
        public byte[] Signature { get; set; }
    }

    public class OKResponse
    {
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }


        [JsonProperty("credentials")]
        public Credentials Credentials { get; set; }


        [JsonProperty("expires_in")]
        public int ExpiresIn { get; set; }
    }

    public class OrderData {
        [JsonProperty("productId")]
        public int ProductId { get; set; }

        [JsonProperty("quantity")]
        public int Quantity { get; set; }

        [JsonProperty("customerReference")]
        public string CustomerReference { get; set; }
    }

    public class NetworkCatalogue
    {
        public override string ToString() {
            return this.Name;
        }

        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("products")]
        public ICollection<ProductSubCatalogue> Products { get; set; }
    }

    public class ProductSubCatalogue
    {
        public override string ToString()
        {
            return this.Description;
        }

        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("voucherType")]
        public int VoucherType { get; set; }

        [JsonProperty("description")]
        public string Description { get; set; }

        [JsonProperty("faceValue")]
        public decimal FaceValue { get; set; }

        [JsonProperty("discountPercentage")]
        public decimal DiscountPercentage { get; set; }
    }

    public class BatchListing {
        [JsonProperty("batch")]
        public Batch Batch { get; set; }

        [JsonProperty("remainingBalance")]
        public decimal RemainingBalance { get; set; }
    }

    public class Batch
    {
        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("orderDate")]
        public DateTime OrderDate { get; set; }

        [JsonProperty("orderGuid")]
        public string OrderGuid { get; set; }

        [JsonProperty("orderReference")]
        public string OrderReference { get; set; }

        [JsonProperty("internalReference")]
        public string InternalReference { get; set; }

        [JsonProperty("networkId")]
        public int NetworkId { get; set; }

        [JsonProperty("networkName")]
        public string NetworkName { get; set; }

        [JsonProperty("productId")]
        public int ProductId { get; set; }

        [JsonProperty("productDescription")]
        public string ProductDescription { get; set; }

        [JsonProperty("voucherType")]
        public int VoucherType { get; set; }

        [JsonProperty("faceValue")]
        public decimal FaceValue { get; set; }

        [JsonProperty("discountPercentage")]
        public decimal DiscountPercentage { get; set; }

        [JsonProperty("requestedQuantity")]
        public int RequestedQuantity { get; set; }

        [JsonProperty("deliveredQuantity")]
        public int DeliveredQuantity { get; set; }

        [JsonProperty("cost")]
        public decimal Cost { get; set; }

        [JsonProperty("readyForDownload")]
        public bool ReadyForDownload { get; set; }
    }

    public class Page<T>
    {
        [JsonProperty("items")]
        public List<T> Items { get; set; }

        [JsonProperty("totalItems")]
        public int TotalItems { get; set; }

        [JsonProperty("pageNumber")]
        public int PageNumber { get; set; }

        [JsonProperty("pageSize")]
        public int PageSize { get; set; }

        [JsonProperty("numPages")]
        public int NumPages { get; set; }
    }

    public enum Vouchertype
    {
        Voucher = 1,
        SMS = 2,
        Data = 3
    }

    public class Voucher
    {
        [JsonProperty("id")]
        public int Id { get; set; }

        [JsonProperty("sequenceNumber")]
        public int SequenceNumber { get; set; }

        [JsonProperty("expiryDate")]
        public DateTime ExpiryDate { get; set; }

        [JsonProperty("serial")]
        public string Serial { get; set; }

        [JsonProperty("encryptedPIN")]
        public string EncryptedPIN { get; set; }
    }

    public class PrintVoucher
    {
        public int SequenceNumber { get; set; }
        public int BatchId { get; set; }
        public string Serial { get; set; }
        public int VoucherId { get; set; }
        public string Description { get; set; }
        public string DecryptedPIN { get; set; }
    }

    public class UserLimits {
        public enum UserLimitTypes {
            OnlinePrint ,
            OnlineReprint,
            OfflinePrint,
            OfflineReprint,
            BulkExport,
            BulkOrder
        }
        public decimal OnlinePrintValue { get; set; }
        public decimal OnlineReprintValue { get; set; }
        public decimal OfflinePrintValue { get; set; }
        public decimal OfflineReprintValue { get; set; }
        public decimal BulkExportValue { get; set; }
        public decimal BulkOrderValue { get; set; }
    }

    public class VendorEvent
    {
        public enum VendorEventType
        {
            Unknown = 0,
            Login = 1, //Logged by Server
            OfflineLogin = 2,
            ExtendLogin = 3, //Logged by Server
            Logout = 4,
            DownloadVoucher = 5, //Logged by Server
            PrintVoucher = 6,
            ViewVoucherPIN = 7,
            ExportVoucher = 8
        }

        public int Id { get; set; }

        public int VendorId { get; set; }

        public int UserId { get; set; }

        public int? VoucherId { get; set; }

        public int? RemoteId { get; set; }

        public DateTimeOffset EventDate { get; set; }

        public VendorEventType EventType { get; set; }

        public bool Retry { get; set; }
    }

    public class EventLog {
        public VendorEvent.VendorEventType EventType { get; set; }
        public int? VoucherId { get; set; }
        public int? BatchId { get; set; }
        public bool Retry { get; set; }
    }

    public class VendorEventsMetaData {
        [JsonProperty("date")]
        public DateTimeOffset Date { get; set; }

        [JsonProperty("vendorId")]
        public int VendorId { get; set; }

        [JsonProperty("lastVendorEventRemoteId")]
        public int? LastVendorEventRemoteId { get; set; }
    }

    public class RemoteVendorEvent
    {
        [JsonProperty("Id")]
        public int? Id { get; set; }

        [JsonProperty("VendorId")]
        public int? VendorId { get; set; }

        [JsonProperty("UserId")]
        public int? UserId { get; set; }

        [JsonProperty("VoucherId")]
        public int? VoucherId { get; set; }

        [JsonProperty("EventDate")]
        public DateTimeOffset? EventDate { get; set; }

        [JsonProperty("EventType")]
        public VendorEvent.VendorEventType? EventType { get; set; }

        [JsonProperty("Retry")]
        public bool Retry { get; set; }
    }

    public class RemoteVendorEventResponse
    {
        [JsonProperty("lastVendorEventRemoteId")]
        public int LastVendorEventRemoteId { get; set; }
    }

    public class InternalReferenceResponse
    {
        [JsonProperty("internalReference")]
        public string InternalReference { get; set; }
    }

    public class OrderList
    {
        public string OrderDate;
        public string OrderReference;
        public string User;
        public string OrderCost;
        public string Balance;
        public List<OrderReportLine> OrderLines;
    }

    public class OrderReportLine {
        public string OrderItem;
        public string QtyOrdered;
        public string QtyDelivered;
        public string Cost;
    }
}
