using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinRT.BxlComponent.Plugin.BxlMpXamarinSDK.Abstractions;
using WinRT.BxlComponent.Plugin.BxlMpXamarinSDK;
using System.Threading;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.Streams;
using System.IO;
using System.Collections.ObjectModel;
using Windows.UI.Core;
using Windows.ApplicationModel.Core;
using System.Runtime.InteropServices.WindowsRuntime;

namespace WinRT.BxlComponent
{
    /* Windows Runtime Component restrictions
        1. All public classes in WinRT / WinMD component should be marked sealed.
        2. public fields aren’t allowed.
        3. public data members must be declared as properties
        4. Data types should be WinRT / WinMD compatible
        5. Creating a WinRT / WinMD component in C++ has some additional property attribute settings (activatable class and etc…)
     */
    public sealed class BxlDeviceInfoEntry
    {
        public string Name { get; set; }
        public string InterfaceType { get; set; }
        public string Address { get; set; }
    }
    public sealed partial class BxlPrinterAPIs
    {
        public string DeviceName { get; private set; }
        public int Open(string deviceName)
        {
            DeviceName = deviceName.Trim();
            return BxlReactNativeSDKHelper.Instance.Open(deviceName);
        }
        public IAsyncOperation<int> Claim(int timeout)
        {
            return Task.Run<int>(async () =>
            {
                //MposDeviceApiWrapper.Instance.CreateDevice(MPosDeviceType.MPOS_DEVICE_PRINTER);
                return await BxlReactNativeSDKHelper.Instance.Claim(DeviceName, timeout > 0 ? (uint)timeout : 0);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> Release()
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.Release();
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> Close()
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.Close();
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> AddEntry(string deviceName, string interfaceType, string address)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.AddEntry(deviceName, interfaceType, address);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> DirectIO([ReadOnlyArray()] byte[] data)
        {
            return Task.Run<int>(async () => {
                return await BxlReactNativeSDKHelper.Instance.DirectIO(data);
            }).AsAsyncOperation();
        }
    }
    public sealed partial class BxlPrinterAPIs
    {
        public IAsyncOperation<int> CheckHealth(int level)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.CheckHealth(level);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> PageModePrint(int mode)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.PageModePrint(mode);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> MarkFeed()
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.DirectIO(new byte[] { 0x0c });
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> CutPaper(int percentage)
        {
            return Task.Run<int>(async () =>
            {
                if(percentage >= 100)
                    return await BxlReactNativeSDKHelper.Instance.DirectIO(new byte[] { 0x08, 0x56, 0x01 });    // Full Cut
                return await BxlReactNativeSDKHelper.Instance.DirectIO(new byte[] { 0x1D, 0x56, 0x00 });        // Partial Cut
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> TransactionPrint(int mode)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.TransactionPrint(mode);
            }).AsAsyncOperation();
        }
    }
    public sealed partial class BxlPrinterAPIs
    {
        public IAsyncOperation<IList<BxlDeviceInfoEntry>> GetEntry()
        {
            return Task.Run<IList<BxlDeviceInfoEntry>>(() =>
            {
                return BxlReactNativeSDKHelper.Instance.GetEntry();
            }).AsAsyncOperation();
        }

        public IAsyncOperation<bool> GetDeviceEnable()
        {
            return Task.Run<bool>(() =>
            {
                return BxlReactNativeSDKHelper.Instance.GetDeviceEnable();
            }).AsAsyncOperation();
        }
        public IAsyncOperation<string> GetPairedDevice()
        {
            return Task.Run<string>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.GetPairedDevice();
            }).AsAsyncOperation();
        }
        public IAsyncOperation<string> GetNetworkDevice(bool wireless, int searchTime /* second */)
        {
            return Task.Run<string>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.GetNetworkDevice(wireless, searchTime);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> GetPrinterStatus()
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.GetPrinterStatus();
            }).AsAsyncOperation();
        }
    }
    public sealed partial class BxlPrinterAPIs
    {
        public int SetCharacterSet(int characterSet)
        {
            return BxlReactNativeSDKHelper.Instance.SetCharacterSet(characterSet);
        }
        public IAsyncOperation<int> SetDeviceEnable(bool enable)
        {
            return Task.Run<int>(() =>
            {
                return BxlReactNativeSDKHelper.Instance.SetDeviceEnable(enable);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> SetPageModePrintDirection(int direction)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.SetPageModePrintDirection(direction);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> SetPageModePrintArea(int x, int y, int width, int height)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.SetPageModePrintArea(x, y, width, height);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> SetPageModeVerticalPosition(int y)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.SetPageModeVerticalPosition(y);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> SetPageModeHorizontalPosition(int x)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.SetPageModeHorizontalPosition(x);
            }).AsAsyncOperation();
        }
    }

    public sealed partial class BxlPrinterAPIs
    {
        public IAsyncOperation<int> PrintNormal(string data)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.PrintNormal(data);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> PrintBarCode(string data, int symbology, int height, int width, int alignment, int hriPosition)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.PrintBarCode(data, symbology, height, width, alignment, hriPosition);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> printBitmapWithURL(string url, int width, int alignment)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.PrintBitmapWithURL(url, width, alignment);
            }).AsAsyncOperation();
        }
        public IAsyncOperation<int> printBitmapWithBase64(string base64String, int width, int alignment)
        {
            return Task.Run<int>(async () =>
            {
                return await BxlReactNativeSDKHelper.Instance.PrintBitmapWithBase64(base64String, width, alignment);
            }).AsAsyncOperation();
        }
    }
    public sealed partial class BxlPrinterAPIs
    {
        // 참조 : https://docs.microsoft.com/en-us/windows/uwp/winrt-components/raising-events-in-windows-runtime-components
        // Declare the event
        public event EventHandler<Object> _dataEvent;
        public event EventHandler<Object> _statusUpdateEvent;
        private void FireStatusUpdateEvent(uint status)
        {
            Task.Run(() => { _statusUpdateEvent?.Invoke(this, (Object)status); });
        }
        private void FireDataEvent(byte[] data)
        {
            Task.Run(() => { _dataEvent?.Invoke(this, (Object)data); });
        }
    }
}
