using System;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using Windows.Storage;
using System.Collections.Generic;

namespace WinRT.BxlComponent.Plugin.BxlMpXamarinSDK.Abstractions
{
    internal class MPosDebug
    {
        public static void WriteLine(string log, string id)
        {
            string time = DateTime.Now.ToString("HH:mm:ss:fff : ");
            System.Diagnostics.Debug.WriteLine(time + "(" + id + ")" + " " + log);
        }
        public static void WriteLine(string log)
        {
            //TextWriterTraceListener writer = new TextWriterTraceListener(System.Console.Out);
            //Debug.Listeners.Add(writer);
            //string time = DateTime.Now.ToString("MM-dd-HH:mm:ss:ffff : ");
            string time = DateTime.Now.ToString("HH:mm:ss:fff : ");
            System.Diagnostics.Debug.WriteLine(time + log);
        }
    }
    internal class MposConnectionInformation
    {
        public MPosInterfaceType IntefaceType { get; set; }
        public string Name { get; set; }
        public string Address
        {
            get
            {
                if (IntefaceType == MPosInterfaceType.MPOS_INTERFACE_BLUETOOTH)
                    return MacAddress;
                return IpAddress + ":" + PortNumber;
            }
        }
        public string MacAddress { get; set; }
        public string IpAddress { get; set; }
        public string PortNumber { get; set; }
        public string BluetoohDeviceId { get; set; }
    }

    internal interface MposLookup
    {
        Task<int> refreshDeivcesList(int interfaceType, int timeout = 3 /*second*/);
        ObservableCollection<MposConnectionInformation> getDeviceList(int interfaceType);
        //Task<int> requestPairing(object obj, string printerName, string pinCode, int timeout = 5 /*second*/);
    }
    internal interface MposConfig : MPosControllerDevices{  
        Task<int[]> searchDevices();

        Task<string> getBgateSerialNumber();
        Task<string> getUSBDevice(int deviceId);
        Task<string> getCustomDevices(int deviceType);
        Task<int[]> getSerialConfiguration(int deviceId);
        Task<int> setSerialConfiguration(int deviceId, int baudRate, int dataBit, int stopBit, int parityBit, int flowControl);
        Task<int> addCustomDevice(int deviceType, string vid, string pid);
        Task<int> deleteCustomDevice(int deviceType, string vid, string pid);
        Task<int> reInitCustomDeviceType(int deviceType);
        Task<string> getSerialNumber(int deviceId);
    }
    internal interface MPosControllerBCD : MPosControllerDevices
    {
        Task<int> displayString(String data, int codePage, int internationalChracterSet, int line);
        Task<int> clearScreen();
        Task<int> storeImage(Object bitmap, int width, int imageNumber);
        Task<int> storeImageFile(String filepath, int width, int imageNumber);
        Task<int> displayImage(int imageNumber, int xPos, int yPos);
        Task<int> clearImage(int imageNumber);
        Task<int> showCursor(int cursor);
    }
    internal interface MPosControllerDallasKey : MPosControllerDevices
    {
    }
    internal interface MPosControllerHID : MPosControllerDevices
    {
    }
    internal interface MPosControllerMSR : MPosControllerDevices
    {
    }
    internal interface MPosControllerNFC : MPosControllerDevices
    {
    }
    internal interface MPosControllerRFID : MPosControllerDevices
    {
    }
    internal interface MPosControllerScale : MPosControllerDevices
    {
    }
    internal interface MPosControllerScanner : MPosControllerDevices{
    }
    internal interface MPosControllerTTYUSB : MPosControllerDevices{
    }
    internal interface MPosControllerUSBSerial : MPosControllerDevices
    {
    }
    
    internal interface IMPosConnection
    {
        MPosInterfaceType _ConnectionType { get; }
        MPosCommandMode _CommandMode { get; set; }
        string _ConnectionInfo { get; set; }
        bool _PageModeInOut { get; set; }
        bool _TransactionModeInOut { get; set; }
        bool isConnected();
        Task<bool> openAsync(MPosDeviceType deviceType, uint timeout = 3 /*second*/);
        Task<bool> closeAsync(uint timeout = 3 /*second*/);
        Task<int> writeAsync(int deviceId, byte[] data, bool storeData = true, bool addBgtHeader = true, uint timeoutInmilliseconds = 3000 /*second*/);
        Task<byte[]> readAsync(uint timeoutInmilliseconds = 3000 /*milliseconds*/);
        void addStatusUpdateEvent(Action<int, byte[]> statusDelegate);
        void removeStatusUpdateEvent(Action<int, byte[]> statusDelegate);
        void addDataReadEvent(Action<int, byte[]> dataDelegate);
        void removeDataReadEvent(Action<int, byte[]> dataDelegate);
        void addDisconnectedEvent(Action disconnectedDelegate);
        void removeDisconnectedEvent(Action disconnectedDelegate);
        void addConnectedEvent(Action connectedDelegate);
        void removeConnectedEvent(Action connectedDelegate);
        void addDeviceListUpdateEvent(Action<int[]> devListDelegate);
        void removeDeviceListUpdateEvent(Action<int[]> devListDelegate);
        Task<bool> isAvailableDeviceId(object deviceType, uint deviceId, uint timeout = 1000);
        Task<int> getLowestDeviceId(uint timeout = 1000, object deviceType = null);
        void setBufferStored(byte[] data, bool addHeaer = true);
        byte[] getBufferStored();
        int[] getAllDeviceId();
        Task<int> clearBufferStored(int deviceId);
    }

    internal interface IMPosConnectionBuilder
    {
        IMPosConnection Build(MPosInterfaceType connectionType, string connectionInfo, int deviceId, int commandMode);
    }
    internal interface MPosControllerDevices
    {
        event Action<byte[]> dataEvent;
                
        event Action<uint> statusUpdateEvent;
        int DeviceID { get; }
        MPosDeviceType DeviceType { get; }
        MPosInterfaceType InterfaceType { get; }
        bool IsOpen { get; }
        MPosCommandMode CommandMode { get; }
        Task<int> openService(uint timeout = 3 /*second*/);
        //Task<int> openService(object context, uint timeout = 3 /*second*/);
        Task<int> closeService(uint closeTimeout = 0 /*second*/);
        bool isOpen();
        int selectCommandMode(int mode);
        int selectInterface(int interfaceType, string address);
        Task<int> setTransaction(int transactionMode);
        Task<int> directIO(byte[] data);
    }
    internal interface MPosControllerPrinter : MPosControllerDevices
    {
        Task<int> printText(string data, MPosFontAttribute attribute = null);
        //Task<int> printText(byte[] data, MPosFontAttribute attribute = null);
        Task<int> print1DBarcode(string data, int symbology, int width, int height, int alignment, int textPosition);
        Task<int> printQRCode(string data, int model, int alignment, int moduleSize, int eccLevel);
        Task<int> printPDF417(string data, int symbology, int alignment, int columnNumber, int rowNumber, int moduleWidth, int moduleHeight, int eccLevel);
        //Task<int> checkPrinterStatus(Action<int> statusReceiver);
        Task<uint> checkPrinterStatus();
        Task<uint> checkBattStatus();
        Task<int> setInternationalCharacterset(int internationalCharacterset);
        int setTextEncoding(int textEncoding);
        Task<int> setCharacterset(int characterset);
        Task<int> asbEnable(bool enable);
        Task<int> printBitmapFile(string path, int width, int alignment, int brightness, bool isDithering, bool isCompress);
        Task<int> printBitmap(object platformImage, int width, int alignment, int brightness, bool isDithering, bool isCompress);
        Task<int> setPagemode(int pageMode);
        int setPagemodePrintArea(int x, int y, int width, int height);
        int setPagemodeDirection(int direction);
        int setPagemodePosition(int x, int y);
        Task<int> getFirmwareVersion(Action<string> versionDelegate);
        Task<int> getModelName(Action<string> modelDelegate);
        Task<int> getCodePageName(Action<string> cpNameDelegate);
    }

    internal interface MPosControllerLabelPrinter : MPosControllerDevices
    {
        // Media & Buffer Related Commands 
        Task<int> setPrintingType(char printingType);
        Task<int> setMargin(int horizontalMargin, int verticalMargin);
        Task<int> setBackFeedOption(bool bEnable, int stepQuantity = 0);
        Task<int> setLength(int labelLength, int gapLength, char mediaType, int offsetLength);
        Task<int> setWidth(int labelWidth);
        Task<int> setBufferMode(bool doubleBufferEnable);
        Task<int> setDensity(int density);
        Task<int> setSpeed(int speed);
        Task<int> setOrientation(char orientation);
        Task<int> setOffset(int offset);
        Task<int> setCuttingPosition(int cuttingPosition);
        Task<int> setAutoCutter(bool enable, int period = 1 /* every page*/);
        int setTextEncoding(int textEncoding);
        Task<int> setCharacterset(int charset, int internationalCharset);
        Task<uint> checkPrinterStatus();
        Task<int> printRawData(byte[] data);
        Task<int> printBuffer(int numberOfCopies);

        // Methods related to print out        
        Task<int> drawTextDeviceFont(string data, int xPos, int yPos, char fontSelection, int fontWidth,
                                int fontHeight, int rightSpace, int rotation, bool reverse, bool bold, bool rightToLeft, int alignment);
        Task<int> drawTextVectorFont(string data, int xPos, int yPos, char fontSelection, int fontWidth, int fontHeight, int rightSpace, int rotation, bool reverse,
                                bool bold, bool italic, bool rightToLeft, int alignment);

        // Methods related to 1d/2d codes
        Task<int> drawBarcode1D(string data, int xPos, int yPos, int barcodeType, int widthNarrow, int widthWide, int height, int hri, int quietZoneWidth, int rotation);
        Task<int> drawBarcodeMaxiCode(string data, int xPos, int yPos, int mode);
        Task<int> drawBarcodePDF417(string data, int xPos, int yPos, int maximumRowCount, int maximumColumnCount, int errorCorrectionLevel,
                                int dataCompressionMethod, bool hri, int barcodeOriginPoint, int moduleWidth, int barHeight, int rotation);

        Task<int> drawBarcodeQRCode(string data, int xPos, int yPos, int size, int model, int errorCorrectionLevel, int rotation);
        Task<int> drawBarcodeDataMatrix(string data, int xPos, int yPos, int size, bool reverse, int rotation);
        Task<int> drawBarcodeAztec(string data, int xPos, int yPos, int size, bool extendedChannel, int errorCorrectionLevel,
                                bool menuSymbol, int numberOfSymbols, string optionalID, int rotation);

        Task<int> drawBarcodeCode49(string data, int xPos, int yPos, int widthNarrow, int widthWide, int height, int hri, int startingMode, int rotation);

        Task<int> drawBarcodeCodaBlock(string data, int xPos, int yPos, int widthNarrow, int widthWide, int height, bool securityLevel,
                                    int numberOfCharactersPerRow, char mode, int numberOfRowToEncode);

        Task<int> drawBarcodeMicroPDF(string data, int xPos, int yPos, int moduleWidth, int moduleHeight, int mode, int rotation);

        Task<int> drawBarcodeIMB(string data, int xPos, int yPos, bool hri, int rotation);
        Task<int> drawBarcodeMSI(string data, int xPos, int yPos, int narrowWidth, int wideWidth, int height, int checkDigitSelection, bool printCheckDigit, int hri, int rotation);
        Task<int> drawBarcodePlessey(string data, int xPos, int yPos, int narrowWidth, int wideWidth, int height, bool printCheckDigit, int hri, int rotation);
        Task<int> drawBarcodeTLC39(string data, int xPos, int yPos, int narrowWidth, int wideWidth, int height, int rowHeightOfMicroPDF417, int narrowWidthOfMicroPDF417, int rotation);
        Task<int> drawBarcodeRSS(string data, int xPos, int yPos, int barcodeType, int magnification, int separatorHeight, int barcodeHeight, int segmentWidth, int rotation);
        Task<int> drawBlock(int startPosX, int startPosY, int endPosX, int endPosY, char option = 'B', int thickness = 2);
        Task<int> drawCircle(int startPosX, int startPosY, int sizeSelection, int multiplier);
        Task<int> drawImageFile(string filePath, int startPosX, int startPosY, int width, int brightness = 50, bool isDithering = true, bool isCompress = true);
        Task<int> drawImage(object bitmapSrc, int startPosX, int startPosY, int width, int brightness = 50, bool isDithering = true, bool isCompress = true);
        Task<int> getFirmwareVersion(Action<string> versionDelegate);
        Task<int> getModelName(Action<string> modelDelegate);
        Task<int> setupRFID(int rfidType, int numberOfRetries, int numberofLabel, int radioPower);
        Task<int> calibrateRFID();
        Task<int> setRFIDPosition(int transPosition);
        Task<int> writeRFID(int dataType, int startingBlockNumber, int dataLength, string data);
        Task<int> setRFIDPassword(string oldAccessPwd, string oldKillPwd, string newAccessPwd, string newKillPwd);
        Task<int> lockRFID();
        Task<int> setEPCDataStructure(int totalSize, string fieldSizes);
    }

    /// <summary>
    /// Interface for MPosDeviceFactory
    /// </summary>
    internal interface IMPosDeviceFactory
    {
        // Factory Method Pattern
        MPosControllerDevices createDevice(MPosDeviceType deviceType);
        //IMPosDeviceControllerDevice createDevice(DeviceType deviceType, ConnectionType connectionType);
    }
}
