using System;
using CPF;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using CPF.Threading;
using System.Collections.Concurrent;
using CPF.Drawing;
using CPF.Input;
using System.Linq;
using CPF.Controls;
using CPF.Platform;
using CPF.Mac.Foundation;
using CPF.Mac.AppKit;
using CPF.Mac.CoreGraphics;
using CPF.Mac.ObjCRuntime;
using System.Diagnostics;

namespace CPF.Mac
{
    //[Register("WindowImpl", true)]
    public class WindowImpl : NSWindow, IWindowImpl, NotMonoMac
    {
        internal NSView view;
        public WindowImpl() : base(new CGRect(0, 0, 10, 10), (NSWindowStyle.Closable | NSWindowStyle.Miniaturizable), NSBackingStore.Nonretained, false)
        {
            AppDelegate.windows.Add(this);
            MinSize = new CGSize(1, 1);
            ContentMinSize = new CGSize(1, 1);
            if (Application.GetDrawingFactory().UseGPU)
            {
                view = new OpenGLView(Frame, this);
            }
            else
            {
                view = new InnerView(Frame, this);
            }

            ContentView = view;
            IsOpaque = false;
            BackgroundColor = NSColor.Clear;
            AcceptsMouseMovedEvents = true;
            HasShadow = false;
            ReleasedWhenClosed = true;

            //RegisterForDraggedTypes(new string[] { NSPasteboard.NSFilenamesType, "*.jpg", "*.jpeg" });
            //ShouldDragDocumentWithEvent = (NSWindow window, NSEvent theEvent, CGPoint dragImageLocation, NSPasteboard withPasteboard) =>
            //{
            //    return true;
            //};
            //DocumentEdited = true;
            //WillReturnFieldEditor = (NSWindow sender, NSObject client) =>
            //{
            //    return FieldEditor(false,client);
            //};

            //WillUseFullScreenPresentationOptions = (s, e) =>
            //{
            //    //return e;
            //    return NSApplicationPresentationOptions.AutoHideToolbar| NSApplicationPresentationOptions.FullScreen| NSApplicationPresentationOptions.AutoHideMenuBar;
            //};
            //this.WindowShouldClose = delegate
            // {
            //     return !Closing();
            // };
            this.DidMiniaturize += (s, e) =>
            {
                //最小化
                windowState = WindowState.Minimized;
                if (WindowStateChanged != null)
                {
                    WindowStateChanged();
                }
            };
            this.DidDeminiaturize += (s, e) =>
            {
                if (windowState == WindowState.Minimized)
                {
                    windowState = WindowState.Normal;
                }
                //取消最小化
                if (WindowStateChanged != null)
                {
                    WindowStateChanged();
                }
            };
            WillClose += WindowImpl_WillClose;
            DidMoved += WindowImpl_DidMoved;
            //scaling = (float)BackingScaleFactor;
        }
        public override void PerformClose(NSObject sender)
        {
            base.PerformClose(sender);
        }
        internal NSEvent LeftMouseDown;
        bool isMouseEnter;
        public override void SendEvent(NSEvent theEvent)
        {
            base.SendEvent(theEvent);
            if (!enable)
            {
                return;
            }
            MouseButton mouseButton;
            switch (theEvent.Type)
            {
                case NSEventType.MouseMoved:
                    var isme = view.HitTest(theEvent.LocationInWindow) != null;
                    if (isme != isMouseEnter)
                    {
                        if (!isme)
                        {
                            mouseButton = Mouse(theEvent);
                            root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseLeave);
                            NSCursor.ArrowCursor.Set();
                        }
                        isMouseEnter = isme;
                    }

                    if (isMouseEnter || root.InputManager.MouseDevice.Captured != null)
                    {
                        mouseButton = Mouse(theEvent);
                        if (!root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove))
                        {
                            if (root.Children.FirstOrDefault(a => a.IsMouseOver) == null)
                            {
                                SetCursor(root.Cursor);
                            }
                        }
                    }
                    break;
                case NSEventType.LeftMouseDown:
                    LeftMouseDown = theEvent;
                    modifiers |= InputModifiers.LeftMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);
                    LeftMouseDown = null;
                    //this.DisableCursorRects();
                    break;
                case NSEventType.LeftMouseUp:
                    //this.EnableCursorRects();
                    modifiers ^= InputModifiers.LeftMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);
                    break;
                case NSEventType.LeftMouseDragged:
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
                    break;
                case NSEventType.RightMouseDown:
                    modifiers |= InputModifiers.RightMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);
                    break;
                case NSEventType.RightMouseUp:
                    modifiers ^= InputModifiers.RightMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);
                    break;
                case NSEventType.RightMouseDragged:
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
                    break;
                case NSEventType.OtherMouseDown:
                    modifiers |= InputModifiers.MiddleMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);
                    break;
                case NSEventType.OtherMouseUp:
                    modifiers ^= InputModifiers.MiddleMouseButton;
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);
                    break;
                case NSEventType.OtherMouseDragged:
                    mouseButton = Mouse(theEvent);
                    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
                    break;
                //case NSEventType.KeyDown:

                //    break;
                //case NSEventType.KeyUp:

                //    break;
                default:
                    break;
            }
        }

        public override void TouchesBeganWithEvent(NSEvent theEvent)
        {
            base.TouchesBeganWithEvent(theEvent);
            Console.WriteLine("TouchesBeganWithEvent");
        }
        public override void TouchesEndedWithEvent(NSEvent theEvent)
        {
            base.TouchesEndedWithEvent(theEvent);
            Console.WriteLine("TouchesEndedWithEvent");
        }
        public override void TouchesCancelledWithEvent(NSEvent theEvent)
        {
            base.TouchesCancelledWithEvent(theEvent);
            Console.WriteLine("TouchesCancelledWithEvent");
        }

        CGPoint oldPoint;
        private void WindowImpl_DidMoved(object sender, EventArgs e)
        {
            UpdateCursor();
            if (PositionChanged != null)
            {
                var h = this.Screen.Bounds.Height;
                var point = new PixelPoint((int)Frame.X, (int)(h - Frame.Height - Frame.Y));
                oldPoint = Frame.Location;
                PositionChanged(point);
            }
        }

        private void WindowImpl_WillClose(object sender, EventArgs e)
        {
            Console.WriteLine("WillClose");
            if (isMainVisible)
            {
                return;
            }
            if (Closed != null)
            {
                Closed();
            }
            //if (parent != null)
            //{
            //    //parent.IsEnabled = true;
            //    (parent.ViewImpl as WindowImpl).enable = false;
            //}
            //parent = null;
            if (root is Window)
            {
                if ((root as Window).IsMain)
                {
                    var app = MacPlatform.Application;
                    app.Terminate(app);
                }
            }
        }
        //public override bool AcceptsMouseMovedEvents { get => true; set => base.AcceptsMouseMovedEvents = value; }
        public override bool CanBecomeKeyWindow => CanActivate;
        public override bool AcceptsFirstResponder()
        {
            return true;
        }
        public override bool CanBecomeMainWindow => true;
        bool validDpi;
        public void InvalidateDpi()
        {
            validDpi = false;
        }
        //double dpi;
        //internal double DPIY
        //{
        //    get
        //    {
        //        if (!validDpi)
        //        {
        //            using (var str = new NSString("NSDeviceResolution"))
        //            {
        //                var screen = base.Screen;
        //                if (screen == null)
        //                {
        //                    screen = NSScreen.MainScreen;
        //                }
        //                var v = screen.DeviceDescription.ObjectForKey(str) as NSValue;
        //                scaling = (float)BackingScaleFactor;
        //                dpi = v.SizeValue.Height;
        //            }
        //        }
        //        return dpi;
        //    }
        //}

        CGRect lastFrame;
        bool validFrame = true;
        internal CPF.Controls.View root;
        //float scaling = 1;
        internal WindowState windowState = WindowState.Normal;
        public Func<bool> Closing { get; set; }
        public Action Closed { get; set; }

        public override void Close()
        {
            isMainVisible = false;
            if (Closing != null)
            {
                if (!Closing.Invoke())
                {
                    base.Close();
                }
            }
            else
            {
                base.Close();
            }
        }

        public WindowState WindowState
        {
            get
            {
                return windowState;
            }
            set
            {
                switch (value)
                {
                    case WindowState.Normal:
                        if (IsMiniaturized)
                        {
                            Deminiaturize(this);
                            lastFrame = Frame;
                        }
                        else
                        {
                            //if ((root as Window).IsFullScreen)
                            //{
                            //    (root as Window).IsFullScreen = false;
                            //}
                            //else
                            //{
                            if (windowState == WindowState.FullScreen)
                            {
                                IsZoomed = false;
                                ToggleFullScreen(this);
                                CollectionBehavior = NSWindowCollectionBehavior.Default;
                            }
                            windowState = WindowState.Normal;
                            if (WindowStateChanged != null)
                            {
                                WindowStateChanged();
                            }
                            if (!validFrame)
                            {
                                var screen = Screen;
                                lastFrame = new CGRect(screen.WorkingArea.X + (screen.WorkingArea.Width * 0.05), screen.WorkingArea.Y + (screen.WorkingArea.Height * 0.05), screen.WorkingArea.Width * 0.9, screen.WorkingArea.Height * 0.9);
                            }
                            SetFrame(lastFrame, true);
                            Position = new PixelPoint((int)lastFrame.X, (int)lastFrame.Y);
                            //}
                        }
                        validFrame = true;
                        //Zoom(this);
                        break;
                    case WindowState.Minimized:
                        //if ((root as Window).IsFullScreen)
                        //{
                        //    setFullScreem = true;
                        //    (root as Window).IsFullScreen = false;
                        //    setFullScreem = false;
                        //}
                        Miniaturize(this);
                        break;
                    case WindowState.Maximized:
                        if (IsMiniaturized)
                        {
                            Deminiaturize(this);
                        }
                        //PerformZoom(this);有窗体边框才行
                        lastFrame = Frame;
                        windowState = WindowState.Maximized;
                        if (WindowStateChanged != null)
                        {
                            WindowStateChanged();
                        }
                        Position = new PixelPoint();
                        if (base.Screen != null)
                        {
                            validFrame = true;
                            SetFrame(base.Screen.VisibleFrame, true);
                        }
                        else
                        {
                            validFrame = false;
                            SetFrame(NSScreen.MainScreen.VisibleFrame, true);
                        }
                        break;
                    case WindowState.FullScreen:
                        if (windowState != WindowState.Minimized)
                        {
                            validFrame = base.Screen != null;
                            lastFrame = Frame;
                        }
                        windowState = WindowState.FullScreen;
                        if (WindowStateChanged != null)
                        {
                            WindowStateChanged();
                        }
                        CollectionBehavior = NSWindowCollectionBehavior.FullScreenPrimary;
                        //base.StyleMask = NSWindowStyle.FullScreenWindow;
                        ToggleFullScreen(this);
                        break;
                }
            }
        }

        //public override void SetFrame(CGRect frameRect, bool display)
        //{
        //    base.SetFrame(frameRect, display);
        //    var w = WindowState.Normal;
        //    if (IsMiniaturized)
        //    {
        //        w = WindowState.Minimized;
        //    }
        //    else if (IsZoomed)
        //    {
        //        w = WindowState.Maximized;
        //    }
        //    if (w != windowState)
        //    {
        //        windowState = w;
        //        if (WindowStateChanged != null)
        //        {
        //            WindowStateChanged();
        //        }
        //    }
        //    if (Resized != null)
        //    {
        //        Resized(new Size((float)frameRect.Width, (float)frameRect.Height));
        //    }
        //}

        public Action WindowStateChanged { get; set; }

        public new Screen Screen { get { return MacPlatform.GetScreen(base.Screen); } }

        public bool CanResize { get; set; }
        public bool IsMain { get; set; }

        public float RenderScaling { get { return (float)BackingScaleFactor * Application.BaseScale; } }

        public Action ScalingChanged { get; set; }
        public Action<Size> Resized { get; set; }
        public Action<PixelPoint> PositionChanged { get; set; }
        public Action Activated { get; set; }
        public Action Deactivated { get; set; }
        public bool CanActivate { get; set; } = true;

        public void SetIMEEnable(bool value)
        {
            if (value)
            {
                this.view.InputContext.Activate();
            }
            else
            {
                //view.InputContext.Deactivate();
                this.view.InputContext.SelectedKeyboardInputSource = "com.apple.keylayout.ABC";
            }
        }

        public float LayoutScaling => Application.BaseScale;

        public PixelPoint Position
        {
            get
            {
                var sc = Screen;
                var h = sc.Bounds.Height;
                var s = root.ActualSize;
                var f = Frame;
                return new PixelPoint((int)f.X, (int)(h - (s.Height * LayoutScaling + f.Y)));
            }
            set
            {
                var sc = Screen;
                var h = sc.Bounds.Height;
                var s = root.ActualSize;
                this.SetFrame(new CGRect(value.X, h - (s.Height * LayoutScaling + value.Y), s.Width * LayoutScaling, s.Height * LayoutScaling), root.Visibility == Visibility.Visible);
                if (oldPoint != Frame.Location)
                {
                    WindowImpl_DidMoved(null, null);
                }
            }
        }

        public void Activate()
        {
            if (CanActivate)
            {
                MakeKeyAndOrderFront(this);
            }
            else
            {
                OrderFront(this);
            }
        }

        public override void ResignKeyWindow()
        {
            base.ResignKeyWindow();
            if (Deactivated != null)
            {
                Deactivated();
            }
        }

        public override void BecomeKeyWindow()
        {
            base.BecomeKeyWindow();
            if (Activated != null)
            {
                Activated();
            }
        }

        public void Capture()
        {
            //throw new NotImplementedException();
        }

        //bool dragMove;
        //CGPoint dragPos;
        //public void DragMove()
        //{
        //    //MovableByWindowBackground = true;
        //    dragMove = true;
        //    dragPos = NSEvent.CurrentMouseLocation;
        //}


        public void Invalidate(in Rect rect)
        {
            var r = new Rect(rect.X * LayoutScaling, rect.Y * LayoutScaling, rect.Width * LayoutScaling, rect.Height * LayoutScaling);
            view.SetNeedsDisplayInRect(new CGRect(r.X - 1, view.Bounds.Height - r.Height - r.Y - 1, r.Width + 2, r.Height + 2));
        }

        public Point PointToScreen(Point point)
        {
            var p = ConvertBaseToScreen(new CGPoint(point.X * LayoutScaling, view.Bounds.Height - point.Y * LayoutScaling));
            var pp = new Point((float)p.X, Screen.Bounds.Height - (float)p.Y);
            //System.Diagnostics.Debug.WriteLine(pp);
            return pp;
        }

        public void ReleaseCapture()
        {
            //throw new NotImplementedException();
        }

        NSCursor cursor;
        public void SetCursor(Cursor cursor)
        {
            var cu = cursor.PlatformCursor as NSCursor;
            if (cu != this.cursor)
            {
                this.cursor = cu;
                UpdateCursor();
            }
            //Debug.WriteLine(cu);
        }

        internal void UpdateCursor()
        {
            if (cursor != null)
            {
                //view.ResetCursorRects();
                //view.AddCursorRect(Frame, cursor);
                cursor.Set();
            }
        }

        public void SetIcon(Image image)
        {

        }

        internal Point imePoint;
        public void SetIMEPosition(Point point)
        {
            imePoint = point;
        }

        public void SetRoot(CPF.Controls.View view)
        {
            root = view;
            root.LayoutUpdated += Root_LayoutUpdated;
        }
        // bool isFirst = true;
        private void Root_LayoutUpdated(object sender, RoutedEventArgs e)
        {
            var b = this.Frame;
            var s = root.ActualSize;
            var l = root.ActualOffset;
            var src = root.Screen;
            var scaling = LayoutScaling;
            var h = src.Bounds.Height;
            if ((int)b.Width != (int)(s.Width * scaling) || (int)b.Height != (int)(s.Height * scaling) || (int)b.X != (int)(l.X * scaling) || (int)b.Y != (int)((h - (s.Height + l.Y) * scaling - src.WorkingArea.Y)))
            {
                //Bounds = new Rect(l.X * scaling, l.Y * scaling, s.Width, s.Height);
                this.SetFrame(new CGRect(l.X * scaling + src.WorkingArea.X, h - (s.Height + l.Y) * scaling - src.WorkingArea.Y, s.Width * scaling, s.Height * scaling), root.Visibility == Visibility.Visible);
                //Console.WriteLine(l + "," + s + "   " + Frame + "   " + src.WorkingArea);
                if (oldPoint != Frame.Location)
                {
                    WindowImpl_DidMoved(null, null);
                }
            }
            //Debug.WriteLine("Root_LayoutUpdated" + s);
        }

        public void SetTitle(string text)
        {
            base.Title = text;
            // base.TitleVisibility = NSWindowTitleVisibility.Visible;
        }

        internal bool isMainVisible;
        public void SetVisible(bool visible)
        {
            if (visible)
            {
                isMainVisible = false;
                if (CanActivate)
                {
                    MakeKeyAndOrderFront(this);
                    //var window = new NSWindow(new CGRect(0, 0, 200, 200), NSWindowStyle.Borderless, NSBackingStore.Buffered, false);
                    //window.ContentView = new GLView(window.Frame, new NSOpenGLPixelFormat());
                    //window.MakeKeyAndOrderFront(window);
                }
                else
                {
                    OrderFront(this);
                }
                root.LayoutManager.ExecuteLayoutPass();
                root.Visibility = Visibility.Visible;
            }
            else
            {
                OrderOut(this);
                isMainVisible = IsMain;
            }
        }

        //Window parent;
        public void ShowDialog(Window window)
        {
            //if (window.ViewImpl != this)
            //{
            //    //window.IsEnabled = false;
            //    (window.ViewImpl as WindowImpl).enable = false;
            //    parent = window;
            //}
            //ReleasedWhenClosed = true;
            this.Level = NSWindowLevel.ModalPanel;
            SetVisible(true);
        }

        public void ShowInTaskbar(bool value)
        {
            //TitleVisibility = value ? NSWindowTitleVisibility.Visible : NSWindowTitleVisibility.Hidden;
        }

        public void TopMost(bool value)
        {
            Level = value ? NSWindowLevel.Floating : NSWindowLevel.Normal;
        }

        //public override void MouseUp(NSEvent theEvent)
        //{
        //    //dragMove = false;
        //    //rs = RS.none;
        //    base.MouseUp(theEvent);
        //    //view.mouseDownCanMoveWindow = false;
        //    modifiers ^= InputModifiers.LeftMouseButton;
        //    //System.Diagnostics.Debug.WriteLine("MouseUp");
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);
        //}

        InputModifiers modifiers = InputModifiers.None;
        MouseButton Mouse(NSEvent theEvent)
        {
            SetModifier();
            MouseButton mouseButton = MouseButton.Left;
            switch (theEvent.Type)
            {
                case NSEventType.LeftMouseDown:
                case NSEventType.LeftMouseUp:
                    mouseButton = MouseButton.Left;
                    break;
                case NSEventType.RightMouseDown:
                case NSEventType.RightMouseUp:
                    mouseButton = MouseButton.Right;
                    break;
                case NSEventType.MouseMoved:
                    break;
                case NSEventType.LeftMouseDragged:
                    break;
                case NSEventType.RightMouseDragged:
                    break;
                case NSEventType.MouseEntered:
                    break;
                case NSEventType.MouseExited:
                    break;
                case NSEventType.KeyDown:
                    break;
                case NSEventType.KeyUp:
                    break;
                case NSEventType.FlagsChanged:
                    break;
                case NSEventType.AppKitDefined:
                    break;
                case NSEventType.SystemDefined:
                    break;
                case NSEventType.ApplicationDefined:
                    break;
                case NSEventType.Periodic:
                    break;
                case NSEventType.CursorUpdate:
                    break;
                case NSEventType.ScrollWheel:
                    break;
                case NSEventType.TabletPoint:
                    break;
                case NSEventType.TabletProximity:
                    break;
                case NSEventType.OtherMouseDown:
                case NSEventType.OtherMouseUp:
                    mouseButton = MouseButton.Middle;
                    break;
                case NSEventType.OtherMouseDragged:
                    break;
                case NSEventType.Gesture:
                    break;
                case NSEventType.Magnify:
                    break;
                case NSEventType.Swipe:
                    break;
                case NSEventType.Rotate:
                    break;
                case NSEventType.BeginGesture:
                    break;
                case NSEventType.EndGesture:
                    break;
                case NSEventType.SmartMagnify:
                    break;
                case NSEventType.QuickLook:
                    break;
                default:
                    break;
            }

            return mouseButton;
        }

        internal void SetModifier()
        {
            var m = NSEvent.CurrentModifierFlags;
            if (modifiers.HasFlag(InputModifiers.Shift))
            {
                modifiers ^= InputModifiers.Shift;
            }
            if (modifiers.HasFlag(InputModifiers.Alt))
            {
                modifiers ^= InputModifiers.Alt;
            }
            if (modifiers.HasFlag(InputModifiers.Control))
            {
                modifiers ^= InputModifiers.Control;
            }
            if (modifiers.HasFlag(InputModifiers.Windows))
            {
                modifiers ^= InputModifiers.Windows;
            }

            switch (m)
            {
                case NSEventModifierMask.AlphaShiftKeyMask:
                    break;
                case NSEventModifierMask.ShiftKeyMask:
                    modifiers |= InputModifiers.Shift;
                    break;
                case NSEventModifierMask.ControlKeyMask:
                    modifiers |= InputModifiers.Control;
                    break;
                case NSEventModifierMask.AlternateKeyMask:
                    modifiers |= InputModifiers.Alt;
                    break;
                case NSEventModifierMask.CommandKeyMask:
                    modifiers |= InputModifiers.Windows;
                    break;
                case NSEventModifierMask.NumericPadKeyMask:
                    break;
                case NSEventModifierMask.HelpKeyMask:
                    break;
                case NSEventModifierMask.FunctionKeyMask:
                    break;
                case NSEventModifierMask.DeviceIndependentModifierFlagsMask:
                    break;
                default:
                    break;
            }
            root.InputManager.KeyboardDevice.Modifiers = modifiers;
        }


        //public override void MouseDown(NSEvent theEvent)
        //{
        //    base.MouseDown(theEvent);
        //    modifiers |= InputModifiers.LeftMouseButton;
        //    var mouseButton = Mouse(theEvent);
        //    //Debug.WriteLine(modifiers);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);
        //}

        //public override void MouseDragged(NSEvent theEvent)
        //{
        //    base.MouseDragged(theEvent);
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
        //}
        //public override void RightMouseDown(NSEvent theEvent)
        //{
        //    base.RightMouseDown(theEvent);
        //    modifiers |= InputModifiers.RightMouseButton;
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);

        //}
        //public override void RightMouseUp(NSEvent theEvent)
        //{
        //    base.RightMouseUp(theEvent);
        //    modifiers ^= InputModifiers.RightMouseButton;
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);

        //}
        //public override void RightMouseDragged(NSEvent theEvent)
        //{
        //    base.RightMouseDragged(theEvent);
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
        //}
        //public override void OtherMouseDown(NSEvent theEvent)
        //{
        //    base.OtherMouseDown(theEvent);
        //    modifiers |= InputModifiers.MiddleMouseButton;
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseDown);

        //}
        //public override void OtherMouseUp(NSEvent theEvent)
        //{
        //    base.OtherMouseUp(theEvent);
        //    modifiers ^= InputModifiers.MiddleMouseButton;
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseButtonEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice, mouseButton), root.LayoutManager.VisibleUIElements, EventType.MouseUp);
        //}
        //public override void OtherMouseDragged(NSEvent theEvent)
        //{
        //    base.OtherMouseDragged(theEvent);
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
        //}

        //public override void MouseMoved(NSEvent theEvent)
        //{
        //    base.MouseMoved(theEvent);
        //    var mouseButton = Mouse(theEvent);
        //    //System.Diagnostics.Debug.WriteLine(modifiers);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseMove);
        //    if (root.Children.FirstOrDefault(a => a.IsMouseOver) == null)
        //    {
        //        (root.Cursor.PlatformCursor as NSCursor).Set();
        //    }
        //}
        //bool isMouseEnter;
        //public override void MouseExited(NSEvent theEvent)
        //{
        //    //isMouseEnter = false;
        //    base.MouseExited(theEvent);
        //    var mouseButton = Mouse(theEvent);
        //    root.InputManager.MouseDevice.ProcessEvent(new MouseEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y), 0, root.InputManager.MouseDevice), root.LayoutManager.VisibleUIElements, EventType.MouseLeave);
        //}
        public override void MouseEntered(NSEvent theEvent)
        {
            base.MouseEntered(theEvent);
            //isMouseEnter = true;
        }
        public override void ScrollWheel(NSEvent theEvent)
        {
            base.ScrollWheel(theEvent);
            if (!enable)
            {
                return;
            }
            var mouseButton = Mouse(theEvent);
            //Debug.WriteLine(theEvent.ScrollingDeltaY);
            root.InputManager.MouseDevice.ProcessEvent(new MouseWheelEventArgs(root, modifiers.HasFlag(InputModifiers.LeftMouseButton), modifiers.HasFlag(InputModifiers.RightMouseButton), modifiers.HasFlag(InputModifiers.MiddleMouseButton), new Point((float)theEvent.LocationInWindow.X, (float)view.Bounds.Height - (float)theEvent.LocationInWindow.Y) / LayoutScaling, root.InputManager.MouseDevice, new Vector((float)(100 * theEvent.DeltaX), (float)(100 * theEvent.DeltaY))), root.LayoutManager.VisibleUIElements, EventType.MouseWheel);
        }

        public override void KeyDown(NSEvent theEvent)
        {
            base.KeyDown(theEvent);
            //root.LayoutManager.ExecuteLayoutPass();
            //if (!string.IsNullOrEmpty(theEvent.Characters))
            //{
            //    root.InputManager.KeyboardDevice.ProcessEvent(new TextInputEventArgs(root, root.InputManager.KeyboardDevice, theEvent.Characters), KeyEventType.TextInput);
            //}
            ////System.Diagnostics.Debug.WriteLine(theEvent.Characters);
            //Keys k;
            //s_KeyMap.TryGetValue(theEvent.KeyCode, out k);
            //SetModifier();
            //root.InputManager.KeyboardDevice.ProcessEvent(new KeyEventArgs(root, k, root.InputManager.KeyboardDevice.Modifiers, root.InputManager.KeyboardDevice), KeyEventType.KeyDown);
        }

        public override void KeyUp(NSEvent theEvent)
        {
            base.KeyUp(theEvent);
            //Debug.WriteLine(theEvent.Characters);
            if (!enable)
            {
                return;
            }
            Keys k;
            Key.s_KeyMap.TryGetValue(theEvent.KeyCode, out k);
            //Console.WriteLine(k + " " + theEvent.KeyCode);
            SetModifier();
            var plat = Application.GetRuntimePlatform() as MacPlatform;
            plat.CurrentKeyEvent = theEvent;
            root.InputManager.KeyboardDevice.ProcessEvent(new KeyEventArgs(root, k, theEvent.KeyCode, root.InputManager.KeyboardDevice.Modifiers, root.InputManager.KeyboardDevice), KeyEventType.KeyUp);

            plat.CurrentKeyEvent = null;
        }
        public override bool PerformKeyEquivalent(NSEvent theEvent)
        {
            if (!enable)
            {
                return true;
            }
            Keys k;
            Key.s_KeyMap.TryGetValue(theEvent.KeyCode, out k);
            if (k == Keys.Back)
            {
                return true;
            }
            //Console.WriteLine(k + " " + theEvent.Characters);
            //Console.WriteLine((int)theEvent.CharactersIgnoringModifiers[0] + "  " + (int)theEvent.Characters[0]);
            //Console.WriteLine(root.InputManager.KeyboardDevice.FocusedElement.ToString() + theEvent.KeyCode);
            SetModifier();
            var plat = Application.GetRuntimePlatform() as MacPlatform;
            plat.CurrentKeyEvent = theEvent;
            root.InputManager.KeyboardDevice.ProcessEvent(new KeyEventArgs(root, k, theEvent.KeyCode, root.InputManager.KeyboardDevice.Modifiers, root.InputManager.KeyboardDevice), KeyEventType.KeyDown);
            plat.CurrentKeyEvent = null;
            //if (!string.IsNullOrEmpty(theEvent.Characters))
            //{
            //    if (!MacPlatform.keyValuePairs.ContainsKey(new KeyGesture(k, root.InputManager.KeyboardDevice.Modifiers)))
            //    {
            //        var uc = char.GetUnicodeCategory(theEvent.Characters[0]);
            //        if (uc != System.Globalization.UnicodeCategory.Control && uc != System.Globalization.UnicodeCategory.PrivateUse)
            //        {
            //            root.InputManager.KeyboardDevice.ProcessEvent(new TextInputEventArgs(root, root.InputManager.KeyboardDevice, theEvent.Characters), KeyEventType.TextInput);
            //        }
            //    }
            //}
            return true;
        }

        protected override void Dispose(bool disposing)
        {
            AppDelegate.windows.Remove(this);
            base.Dispose(disposing);
        }

        public Point PointToClient(Point point)
        {
            var p = base.ConvertScreenToBase(new CGPoint(point.X, Screen.Bounds.Height - point.Y));
            return new Point((float)p.X, (float)view.Bounds.Height - (float)p.Y) / LayoutScaling;
        }

        //bool setFullScreem;
        //public void SetFullscreen(bool fullscreen)
        //{
        //    if (fullscreen)
        //    {
        //        if (windowState != WindowState.Minimized)
        //        {
        //            lastFrame = Frame;
        //        }
        //        if (!setFullScreem)
        //        {
        //            windowState = WindowState.Maximized;
        //            if (WindowStateChanged != null)
        //            {
        //                WindowStateChanged();
        //            }
        //        }
        //        CollectionBehavior = NSWindowCollectionBehavior.FullScreenPrimary;
        //        //base.StyleMask = NSWindowStyle.FullScreenWindow;
        //        ToggleFullScreen(this);
        //    }
        //    else
        //    {
        //        if (!setFullScreem)
        //        {
        //            windowState = WindowState.Normal;
        //            if (WindowStateChanged != null)
        //            {
        //                WindowStateChanged();
        //            }
        //        }
        //        IsZoomed = false;
        //        ToggleFullScreen(this);
        //        CollectionBehavior = NSWindowCollectionBehavior.Default;
        //        Position = new PixelPoint((int)lastFrame.X, (int)lastFrame.Y);
        //        SetFrame(lastFrame, true);
        //    }
        //}
        bool enable = true;
        public void SetEnable(bool enable)
        {
            this.enable = enable;
        }
    }


    //[Register("NSTextInputClient", false)]
    class InnerView : NSView, NotMonoMac, NSTextInputClient
    {
        public InnerView(CGRect rect, WindowImpl window) : base(rect)
        {

            //AddSubview(new NSText(new CGRect(10, 10, 100, 100)) {BackgroundColor=NSColor.FromCGColor(new CGColor(0,0,0,0)), TextColor= NSColor.FromCGColor(new CGColor(0, 0, 0, 0)), CanDrawConcurrently=false });
            this.window = window;
            RegisterForDraggedTypes(new string[] { NSPasteboard.NSPictType, NSPasteboard.NSStringType, NSPasteboard.NSFilenamesType, NSPasteboard.NSHtmlType });
        }

        public override void MouseMoved(NSEvent theEvent)
        {
            base.MouseMoved(theEvent);

            // Debug.WriteLine("MouseMoved" + window);
        }

        public override void MouseDown(NSEvent theEvent)
        {
            InputContext.HandleEvent(theEvent);
        }

        public override void KeyDown(NSEvent theEvent)
        {
            base.KeyDown(theEvent);
            //Keys k;
            //Key.s_KeyMap.TryGetValue(theEvent.KeyCode, out k);
            //if (k == Keys.Back || k == Keys.Tab || k == Keys.Enter)
            //{
            //    return;
            //}
            var r = InputContext.HandleEvent(theEvent);
            //Debug.WriteLine(r);
        }

        public override void MouseDragged(NSEvent theEvent)
        {
            InputContext.HandleEvent(theEvent);
        }
        public override void MouseUp(NSEvent theEvent)
        {
            InputContext.HandleEvent(theEvent);
        }
        WindowImpl window;
        //long bounds;
        //NSTrackingArea bounds;
        //public override void ViewDidMoveToWindow()
        //{
        //    base.ViewDidMoveToWindow();
        //    bounds = new NSTrackingArea(Bounds, NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInKeyWindow, this, new NSDictionary(""));
        //    AddTrackingArea(bounds);
        //}

        //public override void UpdateTrackingAreas()
        //{
        //    base.UpdateTrackingAreas();
        //    RemoveTrackingArea(bounds);
        //    bounds = new NSTrackingArea(Bounds, NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInKeyWindow, this, new NSDictionary(""));
        //    AddTrackingArea(bounds);

        //}
        public override void SetFrameSize(CGSize newSize)
        {
            base.SetFrameSize(newSize);
            //var w = WindowState.Normal;
            //if (window.IsMiniaturized)
            //{
            //    w = WindowState.Minimized;
            //}
            //else if (window.IsZoomed)
            //{
            //    w = WindowState.Maximized;
            //}
            //if (w != window.windowState)
            //{
            //    window.windowState = w;
            //    if (window.WindowStateChanged != null)
            //    {
            //        window.WindowStateChanged();
            //    }
            //}
            window.UpdateCursor();
            if (window.Resized != null)
            {
                window.Resized(new Size((float)newSize.Width, (float)newSize.Height) / window.LayoutScaling);
                //Console.WriteLine(newSize);
            }
        }


        static CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB();
        Size oldSize;
        Bitmap bitmap;
        public override void DrawRect(CGRect dirtyRect)
        {
            if (window.root.IsDisposed)
            {
                return;
            }
            var scaling = (float)window.BackingScaleFactor;
            window.root.LayoutManager.ExecuteLayoutPass();
            var size = new Size((float)Bounds.Width, (float)Bounds.Height) * scaling;
            if (bitmap == null || oldSize != size)
            {
                oldSize = size;
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }
                if (oldSize.Width <= 0 || oldSize.Height <= 0)
                {
                    return;
                }
                bitmap = new Bitmap((int)oldSize.Width, (int)oldSize.Height);
            }
            var context = NSGraphicsContext.CurrentContext.GraphicsPort;

            using (var dc = DrawingContext.FromBitmap(bitmap))
            {
                //dc.Clear(Color.Transparent);
                //var m = dc.Transform;
                //m.ScalePrepend(window.RenderScaling, window.RenderScaling);
                //dc.Transform = m;
                if (window.root.LayoutManager.VisibleUIElements != null)
                {
                    var b = new Rect((float)dirtyRect.X * scaling, ((float)Bounds.Height - (float)dirtyRect.Height - (float)dirtyRect.Y) * scaling, (float)dirtyRect.Width * scaling, (float)dirtyRect.Height * scaling);
                    //Console.WriteLine(b);
                    window.root.RenderView(dc, b);
                }
            }
            using (var lk = bitmap.Lock())
            {
                using (CGBitmapContext bitmapContext = new CGBitmapContext(lk.DataPointer, (int)(bitmap.Width), (int)(bitmap.Height), 8, (int)(bitmap.Width * 4), colorSpace, CGImageAlphaInfo.PremultipliedLast))
                {
                    using (CGImage img = bitmapContext.ToImage())
                    {
                        context.DrawImage(new CGRect(0, 0, bitmap.Width / scaling, bitmap.Height / scaling), img);
                    }
                }
            }


        }
        public override bool CanBecomeKeyView
        {
            get
            {
                return true;
            }
        }


        public override bool AcceptsFirstResponder()
        {
            return true;
        }

        public override bool BecomeFirstResponder()
        {
            return true;
        }
        public override bool ResignFirstResponder()
        {
            return true;
        }
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (bitmap != null)
            {
                bitmap.Dispose();
                bitmap = null;
            }
        }
        public static NSDragOperation ConvertDropEffect(DragDropEffects operation)
        {
            NSDragOperation result = NSDragOperation.None;
            if (operation.HasFlag(DragDropEffects.Copy))
                result |= NSDragOperation.Copy;
            if (operation.HasFlag(DragDropEffects.Move))
                result |= NSDragOperation.Move;
            if (operation.HasFlag(DragDropEffects.Link))
                result |= NSDragOperation.Link;
            return result;
        }

        public static DragDropEffects ConvertDropEffect(NSDragOperation effect)
        {
            DragDropEffects result = DragDropEffects.None;
            if (effect.HasFlag(NSDragOperation.Copy))
                result |= DragDropEffects.Copy;
            if (effect.HasFlag(NSDragOperation.Move))
                result |= DragDropEffects.Move;
            if (effect.HasFlag(NSDragOperation.Link))
                result |= DragDropEffects.Link;
            return result;
        }
        private Point GetDragLocation(CGPoint dragPoint)
        {
            return new Point((float)dragPoint.X, (float)(Frame.Height - dragPoint.Y));
        }
        IDataObject _currentDrag;
        public override NSDragOperation DraggingEntered(NSDraggingInfo sender)
        {
            _currentDrag = new DataObject(sender.DraggingPasteboard);
            //_currentDrag.Get(DataFormat.FileNames);
            var effect = window.root.InputManager.DragDropDevice.DragEnter(new DragEventArgs(_currentDrag, GetDragLocation(sender.DraggingLocation), window.root) { DragEffects = ConvertDropEffect(sender.DraggingSourceOperationMask) }, window.root.LayoutManager.VisibleUIElements);
            return ConvertDropEffect(effect);
        }
        public override NSDragOperation DraggingUpdated(NSDraggingInfo sender)
        {
            _currentDrag = new DataObject(sender.DraggingPasteboard);
            var effect = window.root.InputManager.DragDropDevice.DragOver(new DragEventArgs(_currentDrag, GetDragLocation(sender.DraggingLocation), window.root) { DragEffects = ConvertDropEffect(sender.DraggingSourceOperationMask) }, window.root.LayoutManager.VisibleUIElements);
            return ConvertDropEffect(effect);
        }
        public override void DraggingExited(NSDraggingInfo sender)
        {
            window.root.InputManager.DragDropDevice.DragLeave(window.root.LayoutManager.VisibleUIElements);
            _currentDrag = null;
        }

        public override bool PerformDragOperation(NSDraggingInfo sender)
        {
            //Debug.WriteLine("PerformDragOperation");
            window.root.InputManager.DragDropDevice.Drop(new DragEventArgs(_currentDrag, GetDragLocation(sender.DraggingLocation), window.root) { DragEffects = ConvertDropEffect(sender.DraggingSourceOperationMask) }, window.root.LayoutManager.VisibleUIElements);
            return true;
            //return base.PerformDragOperation(sender);
        }

        [Export("doCommandBySelector:")]
        public virtual void DoCommandBySelector(Selector selector)
        {
            //Debug.WriteLine(selector.Name);
            if (selector.Name == "deleteBackward:")
            {
                window.SetModifier();
                window.root.InputManager.KeyboardDevice.ProcessEvent(new KeyEventArgs(window.root, Keys.Back, Key.kVK_Delete, window.root.InputManager.KeyboardDevice.Modifiers, window.root.InputManager.KeyboardDevice), KeyEventType.KeyDown);
            }
        }


        [Export("baselineDeltaForCharacterAtIndex:")]
        public virtual float GetBaselineDelta(uint charIndex)
        {
            throw new You_Should_Not_Call_base_In_This_Method();
        }

        [Export("characterIndexForPoint:")]
        public virtual uint GetCharacterIndex(CGPoint point)
        {
            //throw new You_Should_Not_Call_base_In_This_Method();
            return 0;
        }

        [Export("firstRectForCharacterRange:actualRange:")]
        public virtual CGRect GetFirstRect(NSRange characterRange, out NSRange actualRange)
        {
            actualRange = new NSRange(0, 0);
            return new CGRect(window.Frame.X + window.imePoint.X, window.Frame.Y + (window.Frame.Height - window.imePoint.Y - 15), 1, 10);
        }

        [Export("fractionOfDistanceThroughGlyphForPoint:")]
        public virtual float GetFractionOfDistanceThroughGlyph(CGPoint point)
        {
            return 0;
        }

        [Export("insertText:replacementRange:")]
        public virtual void InsertText(NSObject text, NSRange replacementRange)
        {
            //throw new You_Should_Not_Call_base_In_This_Method();
            //Console.WriteLine("输入法输出:" + text);
            window.root.InputManager.KeyboardDevice.ProcessEvent(new TextInputEventArgs(window.root, window.root.InputManager.KeyboardDevice, text.ToString()), KeyEventType.TextInput);
            InputContext.InvalidateCharacterCoordinates();
        }

        [Export("setMarkedText:selectedRange:replacementRange:")]
        public virtual void SetMarkedText(NSObject text, NSRange selectedRange, NSRange replacementRange)
        {
            InputContext.InvalidateCharacterCoordinates();
        }

        [Export("unmarkText")]
        public virtual void UnmarkText()
        {
            InputContext.DiscardMarkedText();
        }

        [Export("attributedSubstringForProposedRange:actualRange:")]
        public NSAttributedString GetAttributedSubstring(NSRange proposedRange, out NSRange actualRange)
        {
            actualRange = new NSRange(0, 0);
            return null;
        }

        public virtual bool HasMarkedText
        {
            [Export("hasMarkedText")]
            get
            {
                return false;
            }
        }

        public virtual NSRange MarkedRange
        {
            [Export("markedRange")]
            get
            {
                return new NSRange(0, 0);
            }
        }

        public virtual NSRange SelectedRange
        {
            [Export("selectedRange")]
            get
            {
                return new NSRange(0, 0);
            }
        }

        public virtual NSString[] ValidAttributesForMarkedText
        {
            [Export("validAttributesForMarkedText")]
            get
            {
                return new NSString[] { NSAttributedString.MarkedClauseSegmentAttributeName, NSAttributedString.GlyphInfo, };
            }
        }

        public virtual NSWindowLevel WindowLevel
        {
            [Export("windowLevel")]
            get
            {
                return window.Level;
            }
        }

        //[Export("attributedString")]
        //public NSAttributedString AttributedString => null;
    }

    public class PopImpl : WindowImpl, IPopupImpl
    {
        public PopImpl()
        {
            this.Level = NSWindowLevel.PopUpMenu;
        }

        //public override bool CanBecomeKeyWindow => CanActivate;
    }
}