using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Cosmos.BaseFrame;
using Cosmos.Common;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Reflection;
using SPC.Kiosk.Base;
namespace SPC.Kiosk.Common
{
    /// <summary>
    /// Resource Management Class
    /// </summary>
    public static class ResourceManager
    {
        #region [ Resource Path  ]
        public static string BinPath
        {
            get
            {
                try
                {
                    return BaseCom.NxBinPath;
                }
                catch
                {

                    return @"C:\SPC\POS\BIN";
                }
            }
        }
        public static string SignDataPath
        {
            get
            {
                try
                {
                    return BaseCom.NxDataPath + "SIGN\\";
                }
                catch 
                {

                    return @"C:\temp\";
                }
            }
        }

        /// <summary>
        /// Get CDP Image File(Path)
        /// </summary>
        /// <param name="_imageFileName">Path without Filename</param>
        /// <returns></returns>
        public static string GetCDPimagePath(string _imageFileName)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxCDPPath + CommonValue.IntroMediaPath , _imageFileName);
                if (File.Exists(ImagePath))
                {
                    result = ImagePath;
                }
                else
                {
                    ImagePath = Path.Combine(BaseCom.NxImgPath, _imageFileName);
                    if (File.Exists(ImagePath)) result = ImagePath;
                }
            }
            catch
            {
                result = null;
            }
            return result;
        }
        
        /// <summary>
        /// Get Default Image File(Path)
        /// </summary>
        /// <param name="_imageFileName">Path without Filename</param>
        /// <returns></returns>
        public static string GetNximagePath(string _imageFileName)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxImgPath, _imageFileName);
                if (File.Exists(ImagePath)) result = ImagePath;
            }
            catch
            {
                result = null;
            }
            return result;
        }
        /// <summary>
        ///  Get Default Image File(Path) under Add path
        /// </summary>
        /// <param name="_imageFileName"></param>
        /// <param name="_addPath"></param>
        /// <returns></returns>
        public static string GetNximagePathAdd(string _imageFileName,string _addPath)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxImgPath + _addPath, _imageFileName);
                if (File.Exists(ImagePath)) result = ImagePath;
            }
            catch
            {
                result = null;
            }
            return result;
        }
        /// <summary>
        ///  Get CDP media File(Path)
        /// </summary>
        /// <param name="_mediaFileName">Path without Filename</param>
        /// <returns></returns>
        public static string GetCDPmediaPath(string _mediaFileName)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxCDPPath + PosConst.MST_IMG_PATH.CUSTOMER, _mediaFileName);
                if (File.Exists(ImagePath)) result = ImagePath;
            }
            catch
            {
                result = null;
            }
            return result;
        }
        /// <summary>
        /// Get CDP Item Image  File (Path)
        /// </summary>
        /// <param name="_ItemImageFileName"></param>
        /// <returns></returns>
        public static string GetCDPItemImagePath(string _ItemImageFileName)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxCDPPath + PosConst.MST_IMG_PATH.ITEM, _ItemImageFileName);
                if (File.Exists(ImagePath)) result = ImagePath;
            }
            catch
            {
                result = null;
            }
            return result;
        }

        /// <summary>
        /// Get CDP Option Item Image  File (Path)
        /// </summary>
        /// <param name="_ItemImageFileName"></param>
        /// <returns></returns>
        public static string GetCDPOptionImagePath(string _ItemImageFileName)
        {
            string result = null;
            try
            {
                string ImagePath = Path.Combine(BaseCom.NxCDPPath + PosConst.MST_IMG_PATH.OPTION, _ItemImageFileName);
                if (File.Exists(ImagePath)) result = ImagePath;
            }
            catch
            {
                result = null;
            }
            return result;
        }

        /// <summary>
        /// All CDP Item Images
        /// </summary>
        /// <param name="_searchKey"></param>
        /// <returns></returns>
        public static string[] GetItemImages(string _searchKey)
        {
            string itemImagePath = Path.Combine(BaseCom.NxCDPPath, PosConst.MST_IMG_PATH.ITEM);
            return Directory.GetFiles(itemImagePath, _searchKey);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="_path"></param>
        /// <returns></returns>
        public static BitmapImage LoadBitmapImage(string _path)
        {
            var bitmapImage = default(BitmapImage);
            try
            {
                if (File.Exists(_path))
                {
                    byte[] byteArray = null;
                    using (var fileStream = new FileStream(_path, FileMode.Open, FileAccess.Read))
                    {
                        using (var binaryReader = new BinaryReader(fileStream))
                        {
                            byteArray = binaryReader.ReadBytes((int)fileStream.Length);
                        }
                    }
                    var memoryStream = new MemoryStream(byteArray);
                    bitmapImage = new BitmapImage();
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = memoryStream;
                    bitmapImage.EndInit();
                }
            }
            catch 
            {
                bitmapImage = default(BitmapImage);
            }
            return bitmapImage;
        }
        /// <summary>
        /// Get Bitmap Image From Cache 
        /// If Not Exist Add Chache
        /// </summary>
        /// <param name="_path"></param>
        /// <returns></returns>
        public static BitmapImage GetBitmapImage(string _path)
        {
            BitmapImage getIamge = null;
            try
            {
                if (!_path.CacheContain<BitmapImage>()) _path.AddCache(LoadBitmapImage(_path));
                getIamge = _path.CacheContain<BitmapImage>() ? _path.GetCache<BitmapImage>() : default(BitmapImage); 

            }
            catch (Exception ex)
            {
                CommonLog.ErrorLogWrite("SPC.Kiosk.Common", "ResourceManager", "GetBitmapImage()", "Fail !!", string.Format("{0}\n{1}", ex.Message, ex.StackTrace));
                getIamge = null;
            }
            return getIamge;
        }
        /// <summary>
        /// BitmapImage from UriPath
        /// </summary>
        /// <param name="_uriPath"></param>
        /// <returns></returns>
        public static BitmapImage GetUriBitmapImage(string _uriPath)
        {
            BitmapImage getIamge = null;
            try
            {
                getIamge = new BitmapImage(new Uri(_uriPath));

            }
            catch (Exception)
            {
                getIamge = null;
            }
            return getIamge;
        }
        public static string GetItemImage(this string _ImageFile, string _itemDefaultBrush)
        {
            string result = _itemDefaultBrush;
            try
            {
                if (!string.IsNullOrEmpty(_ImageFile))
                {
                    result = GetCDPItemImagePath(_ImageFile);
                    if (string.IsNullOrEmpty(result)) result = _itemDefaultBrush;
                }
                else
                {
                    result = _itemDefaultBrush;
                }
            }
            catch 
            {
                result = _itemDefaultBrush;
            }
            return result;
        }

        public static string GetOptionImage(this string _ImageFile, string _optionDefaultBrush)
        {
            string result = _optionDefaultBrush;
            try
            {
                if (!string.IsNullOrEmpty(_ImageFile))
                {
                    result = GetCDPOptionImagePath(_ImageFile);
                    if (string.IsNullOrEmpty(result)) result = _optionDefaultBrush;
                }
                else
                {
                    result = _optionDefaultBrush;
                }
            }
            catch
            {
                result = _optionDefaultBrush;
            }
            return result;
        }

        #endregion Resource Path

        #region [ SetBrush ]
        /// <summary>
        /// Get image Brush by BitmapImage
        /// </summary>
        /// <param name="_getObject"></param>
        /// <param name="_bitmapImage"></param>
        /// <param name="_stretch"></param>
        /// <param name="_size"></param>
        /// <param name="_widthProperty"></param>
        /// <param name="_HeightProperty"></param>
        /// <returns></returns>
        public static ImageBrush GetImageBrush(DependencyObject _getObject
                                             , BitmapImage _bitmapImage
                                             , Stretch _stretch
                                             , Size _size
                                             , PropertyInfo _widthProperty
                                             , PropertyInfo _HeightProperty
                                             , double _offsetX = 0d
                                             , double _offsetY = 0d)
        {
            ImageBrush imageBrush = null;
            try
            {
                imageBrush = new ImageBrush(_bitmapImage);
                var imgSource = imageBrush.ImageSource as BitmapImage;
                var ratio = _size.Width / imgSource.PixelWidth;
                switch (_stretch)
                {
                    case Stretch.UniformToFill:
                        imageBrush.Stretch = Stretch.UniformToFill;
                        _widthProperty.SetValue(_getObject, imgSource.PixelWidth, null);
                        _HeightProperty.SetValue(_getObject, imgSource.PixelHeight, null);
                        break;
                    case Stretch.Fill:
                        if (!_size.Width.Equals(double.NaN))
                        {
                            imageBrush.Stretch = Stretch.Fill;
                            _widthProperty.SetValue(_getObject, _size.Width, null);
                            _HeightProperty.SetValue(_getObject, imgSource.PixelHeight * ratio, null);
                        }
                        break;
                    case Stretch.Uniform:
                        imageBrush.Stretch = Stretch.Uniform;
                        _widthProperty.SetValue(_getObject, _size.Width.Equals(double.NaN) ? imgSource.PixelWidth : _size.Width, null);
                        _HeightProperty.SetValue(_getObject, _size.Height.Equals(double.NaN) ? imgSource.PixelHeight : _size.Height, null);
                        break;
                    case Stretch.None:
                        imageBrush.Stretch = Stretch.Fill;
                        _widthProperty.SetValue(_getObject, imgSource.PixelWidth, null);
                        _HeightProperty.SetValue(_getObject, imgSource.PixelHeight, null);
                        break;
                }
                if (!_offsetX.Equals(0d) || !_offsetY.Equals(0d))
                {
                    imageBrush.Transform = new TranslateTransform(_offsetX, _offsetY);
                } 
            }
            catch (Exception ex)
            {
                CommonLog.ErrorLogWrite("SPC.Kiosk.Common", "ResourceManager", "GetImageBrush()", "Fail !!", string.Format("{0}\n{1}", ex.Message, ex.StackTrace));
                imageBrush = null;
            }
            return imageBrush;
        }
        public static void SetBrush(DependencyObject _getObject, string _setProperty, string _getBlush, Stretch _stretch = Stretch.None, Size _size = new Size())
        {
            SetBrush( _getObject,  _setProperty,  _getBlush, 0d, 0d,  _stretch,  _size);
        }
        /// <summary>
        /// Set a Brush by String to Object Property
        /// </summary>
        public static void SetBrush(DependencyObject _getObject, string _setProperty, string _getBlush,double _imageOffsetX, double _imageOffsetY,  Stretch _stretch = Stretch.None, Size _size = new Size())
        {
            Brush result = default(Brush);
            try
            {

                Type getObjectType = _getObject.GetType();
                var widthProperty = getObjectType.GetProperty("Width");
                var HeightProperty = getObjectType.GetProperty("Height");
                if (_getBlush.StartsWith("#"))
                {
                    //String start with '#' (a Byte Data Color)
                    var colorByteString = _getBlush.Replace("#", "");
                    //RGB
                    if (colorByteString.Length.Equals(6))
                    {
                        byte byteRed = (byte)Convert.ToInt16(colorByteString.Substring(0, 2), 16);
                        byte byteGreen = (byte)Convert.ToInt16(colorByteString.Substring(2, 2), 16);
                        byte byteBlue = (byte)Convert.ToInt16(colorByteString.Substring(4, 2), 16);
                        if (!_size.Width.Equals(double.NaN) && _size.Width > 0) widthProperty.SetValue(_getObject, _size.Width, null);
                        if (!_size.Height.Equals(double.NaN) && _size.Height > 0) HeightProperty.SetValue(_getObject, _size.Height, null);
                        result = new SolidColorBrush(Color.FromRgb(byteRed, byteGreen, byteBlue));
                    }
                    //SRGB
                    if (colorByteString.Length.Equals(8))
                    {
                        byte byteAlpa = (byte)Convert.ToInt16(colorByteString.Substring(0, 2), 16);
                        byte byteRed = (byte)Convert.ToInt16(colorByteString.Substring(2, 2), 16);
                        byte byteGreen = (byte)Convert.ToInt16(colorByteString.Substring(4, 2), 16);
                        byte byteBlue = (byte)Convert.ToInt16(colorByteString.Substring(6, 2), 16);
                        if (!_size.Width.Equals(double.NaN) && _size.Width > 0) widthProperty.SetValue(_getObject, _size.Width, null);
                        if (!_size.Height.Equals(double.NaN) && _size.Height > 0) HeightProperty.SetValue(_getObject, _size.Height, null);
                        result = new SolidColorBrush(Color.FromScRgb(byteAlpa, byteRed, byteGreen, byteBlue));
                    }
                }
                else if (_getBlush.StartsWith("pack://") && _getBlush.Contains(";component/"))
                {
                    if (GetUriBitmapImage(_getBlush) is BitmapImage bitMapImage)
                    {
                        result = GetImageBrush(_getObject, bitMapImage, _stretch, _size, widthProperty, HeightProperty, _imageOffsetX, _imageOffsetY);
                    }
                }
                else
                {

                    //String start with out '#' (Not Byte Color)
                    var ColorNameProperties = typeof(Colors).GetProperties();
                    bool FindColor = false;
                    //is Color Name ?
                    foreach (var aColorNamePropertie in ColorNameProperties)
                    {
                        if (aColorNamePropertie.Name.Equals(_getBlush))
                        {
                            FindColor = true;
                            result = new SolidColorBrush((Color)ColorConverter.ConvertFromString(_getBlush));
                        }
                    }
                    if (!FindColor)
                    {
                        //Is Not Colors
                        if (GetBitmapImage(_getBlush) is BitmapImage bitMapImage)
                        {
                            result = GetImageBrush(_getObject, bitMapImage, _stretch, _size, widthProperty, HeightProperty, _imageOffsetX, _imageOffsetY);
                        }
                    }
                    else
                    {
                        //Is Colors Set Brush Size
                        if (!_size.Width.Equals(double.NaN) && _size.Width > 0) widthProperty.SetValue(_getObject, _size.Width, null);
                        if (!_size.Height.Equals(double.NaN) && _size.Height > 0) HeightProperty.SetValue(_getObject, _size.Height, null);

                    }
                }
                var setProperty = getObjectType.GetProperty(_setProperty);
                if (setProperty != null)
                {
                    setProperty.SetValue(_getObject, result == null ? default(Brush) : result, null);
                }
                

            }
            catch (Exception ex)
            {
                CommonLog.ErrorLogWrite("SPC.Kiosk.Common", "ResourceManager", "SetBrush()", "Fail !!", string.Format("{0}\n{1}", ex.Message, ex.StackTrace));
                result = default(Brush);
            }
        }
        #endregion SetBrush

        #region [ GetCursorByImage ]
        [StructLayout(LayoutKind.Sequential)]
        private struct IconInfo
        {
            public bool fIcon;
            public int xHotspot;
            public int yHotspot;
            public IntPtr hbmMask;
            public IntPtr hbmColor;
        }
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
        [DllImport("user32.dll")]
        private static extern IntPtr CreateIconIndirect(ref IconInfo icon);
        /// <summary>
        /// Get Cursor By a Image
        /// </summary>
        /// <param name="_ImageFilePath"></param>
        /// <param name="_cursorHotSpot"></param>
        /// <param name="_targetWidth"></param>
        /// <returns></returns>
        public static Cursor GetCursorByImage(string _ImageFilePath, HotSpotType _cursorHotSpot, double _targetWidth = 0d)
        {
            Cursor _cursor = null;
            try
            {
                var bitmapImage = GetBitmapImage(_ImageFilePath);
                if (bitmapImage != default(BitmapImage))
                {
                    var curImage = new Image {Source = bitmapImage };
                    using (MemoryStream ms = new MemoryStream())
                    {
                        PngBitmapEncoder encoder = new PngBitmapEncoder();
                        double ImageScale = _targetWidth.Equals(0) || _targetWidth.Equals(double.NaN) ? 1d : _targetWidth / curImage.Source.Width;
                        var bitmapFrame = new TransformedBitmap((BitmapSource)curImage.Source, new ScaleTransform(ImageScale, ImageScale));
                        encoder.Frames.Add(BitmapFrame.Create((BitmapSource)bitmapFrame));
                        encoder.Save(ms);
                        var cursorBitmap = new System.Drawing.Bitmap(ms);
                        var intPrt = cursorBitmap.GetHicon();
                        var iconInfo = new IconInfo();
                        GetIconInfo(intPrt, ref iconInfo);
                        switch (_cursorHotSpot)
                        {
                            case HotSpotType.LeftTop:
                                iconInfo.xHotspot = 0;
                                iconInfo.yHotspot = 0;
                                break;
                            case HotSpotType.LeftCenter:
                                iconInfo.xHotspot = 0;
                                iconInfo.yHotspot = cursorBitmap.Height / 2;
                                break;
                            case HotSpotType.LeftBottom:
                                iconInfo.xHotspot = 0;
                                iconInfo.yHotspot = cursorBitmap.Height;
                                break;
                            case HotSpotType.CenterTop:
                                iconInfo.xHotspot = cursorBitmap.Width / 2;
                                iconInfo.yHotspot = 0;
                                break;
                            case HotSpotType.Center:
                                iconInfo.xHotspot = cursorBitmap.Width / 2;
                                iconInfo.yHotspot = cursorBitmap.Height / 2;
                                break;
                            case HotSpotType.CenterBottom:
                                iconInfo.xHotspot = cursorBitmap.Width / 2;
                                iconInfo.yHotspot = cursorBitmap.Height;
                                break;
                            case HotSpotType.RightTop:
                                iconInfo.xHotspot = cursorBitmap.Width;
                                iconInfo.yHotspot = 0;
                                break;
                            case HotSpotType.RightCenter:
                                iconInfo.xHotspot = cursorBitmap.Width;
                                iconInfo.yHotspot = cursorBitmap.Height / 2;
                                break;
                            case HotSpotType.RightBottom:
                                iconInfo.xHotspot = cursorBitmap.Width;
                                iconInfo.yHotspot = cursorBitmap.Height;
                                break;
                        }
                        iconInfo.fIcon = false;
                        intPrt = CreateIconIndirect(ref iconInfo);
                        _cursor = CursorInteropHelper.Create(new SafeFileHandle(intPrt, false));
                    }
                }
            }
            catch (Exception ex)
            {
                CommonLog.ErrorLogWrite("SPC.Kiosk.Common", "ResourceManager", "GetCursorByImage()", "Fail !!", string.Format("{0}\n{1}", ex.Message, ex.StackTrace));
                _cursor = null;
            }
            return _cursor;
        }
        #endregion GetCursorByImage

            

    }

}
