using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using Telerik.WinControls.UI;
using Telerik.WinControls;
using System.Runtime.InteropServices;

namespace Telerik.QuickStart.WinControls
{
    public class ImagePanel : Panel
    {
        private Image topLeftImage;
        private Image topRightImage;
        private Orientation orientation;

        public ImagePanel()
        {
            this.SetStyle( ControlStyles.ResizeRedraw, true );
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle( ControlStyles.OptimizedDoubleBuffer, true );

            this.orientation = Orientation.Horizontal;
        }

        [DefaultValue( Orientation.Horizontal ), Localizable( true ), Description( "Panel orientation" ), Category( "Appearance" )]
        public Orientation Orientation
        {
            get
            {
                return orientation;
            }
            set
            {
                if (this.orientation != value)
                {
                    this.orientation = value;
                    this.Invalidate();
                }
            }
        }


        [DefaultValue( (string)null ), Localizable( true ), Description( "Background left top image" ), Category( "Appearance" )]
        public virtual Image TopLeftImage
        {
            get
            {
                return topLeftImage;
            }
            set
            {
                if (this.topLeftImage != value)
                {
                    this.topLeftImage = value;
                    //this.OnTopLeftImageChanged(EventArgs.Empty);
                }
            }
        }

        [DefaultValue( (string)null ), Localizable( true ), Description( "Background right top image" ), Category( "Appearance" )]
        public virtual Image TopRightImage
        {
            get
            {
                return topRightImage;
            }
            set
            {
                if (this.topRightImage != value)
                {
                    this.topRightImage = value;
                    //this.OnTopLeftImageChanged(EventArgs.Empty);
                }
            }
        }

        [DefaultValue(true)]
        public bool EnableResizing
        {
            get { return enableResizing; }
            set { enableResizing = value; }
        }

        //protected override void OnPaintBackground( PaintEventArgs e )
        //{
        //}

        protected override void OnPaint( PaintEventArgs e )
        {
            if (this.TopLeftImage != null && this.TopRightImage != null && this.BackgroundImage != null)
            {
                Rectangle tileRect = Rectangle.Empty;
                Rectangle clipRect = Rectangle.Empty;

                //using (Brush brush = new SolidBrush( this.BackColor ))
                //{
                //    e.Graphics.FillRectangle( brush, this.ClientRectangle );
                //}

                switch (this.Orientation)
                {
                    case Orientation.Horizontal:                                               

                        int imageMaxHeight = this.BackgroundImage.Height;
                        int rightWidth = this.Width - this.topRightImage.Width;

                        tileRect = new Rectangle(
                            this.topLeftImage.Width,
                            0,
                            this.Width - this.topLeftImage.Width - this.topRightImage.Width,
                            imageMaxHeight );

                        clipRect = Rectangle.Intersect( e.ClipRectangle, tileRect );

                        DrawBackgroundImage(e.Graphics, this.BackgroundImage, BackColor, this.BackgroundImageLayout, tileRect, clipRect, Point.Empty, this.RightToLeft);

                        e.Graphics.DrawImage( this.topLeftImage, new Rectangle( Point.Empty, this.topLeftImage.Size) );
                        e.Graphics.DrawImage(this.topRightImage, new Rectangle(new Point(rightWidth, 0), this.topRightImage.Size));                        

                        break;

                    case Orientation.Vertical:                                         
                        
                        int imageMaxWidth = this.BackgroundImage.Width;                        
                        int bottomHeigt = this.Height - this.topRightImage.Height;

                        tileRect = new Rectangle(
                            0,
                            this.topLeftImage.Height,
                            imageMaxWidth,
                            this.Height - this.topLeftImage.Height - this.topRightImage.Height
                            );

                        clipRect = Rectangle.Intersect( e.ClipRectangle, tileRect );

                        DrawBackgroundImage( e.Graphics, this.BackgroundImage, BackColor, this.BackgroundImageLayout, tileRect, clipRect, Point.Empty, this.RightToLeft );

                        e.Graphics.DrawImage( this.topLeftImage, Point.Empty );
                        e.Graphics.DrawImage( this.topRightImage, new Point( 0, bottomHeigt ) );
                        break;
                }
            }
            else
            {
                base.OnPaintBackground( e );
            }

        }

        internal static void DrawBackgroundImage( Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft )
        {
            if (g == null)
            {
                throw new ArgumentNullException( "g" );
            }
            if (backgroundImageLayout == ImageLayout.Tile)
            {
                using (TextureBrush brush1 = new TextureBrush( backgroundImage, WrapMode.Tile ))
                {
                    if (scrollOffset != Point.Empty)
                    {
                        Matrix matrix1 = brush1.Transform;
                        matrix1.Translate( (float)scrollOffset.X, (float)scrollOffset.Y );
                        brush1.Transform = matrix1;
                    }
                    g.FillRectangle( brush1, clipRect );
                    return;
                }
            }
            Rectangle rectangle1 = CalculateBackgroundImageRectangle( bounds, backgroundImage, backgroundImageLayout );
            if (( rightToLeft == RightToLeft.Yes ) && ( backgroundImageLayout == ImageLayout.None ))
            {
                rectangle1.X += clipRect.Width - rectangle1.Width;
            }
            using (SolidBrush brush2 = new SolidBrush( backColor ))
            {
                g.FillRectangle( brush2, clipRect );
            }
            if (!clipRect.Contains( rectangle1 ))
            {
                if (( backgroundImageLayout == ImageLayout.Stretch ) || ( backgroundImageLayout == ImageLayout.Zoom ))
                {
                    rectangle1.Intersect( clipRect );
                    g.DrawImage( backgroundImage, rectangle1 );
                }
                else if (backgroundImageLayout == ImageLayout.None)
                {
                    rectangle1.Offset( clipRect.Location );
                    Rectangle rectangle2 = rectangle1;
                    rectangle2.Intersect( clipRect );
                    Rectangle rectangle3 = new Rectangle( Point.Empty, rectangle2.Size );
                    g.DrawImage( backgroundImage, rectangle2, rectangle3.X, rectangle3.Y, rectangle3.Width, rectangle3.Height, GraphicsUnit.Pixel );
                }
                else
                {
                    Rectangle rectangle4 = rectangle1;
                    rectangle4.Intersect( clipRect );
                    Rectangle rectangle5 = new Rectangle( new Point( rectangle4.X - rectangle1.X, rectangle4.Y - rectangle1.Y ), rectangle4.Size );
                    g.DrawImage( backgroundImage, rectangle4, rectangle5.X, rectangle5.Y, rectangle5.Width, rectangle5.Height, GraphicsUnit.Pixel );
                }
            }
            else
            {
                ImageAttributes attributes1 = new ImageAttributes();
                attributes1.SetWrapMode( WrapMode.TileFlipXY );
                g.DrawImage( backgroundImage, rectangle1, 0, 0, backgroundImage.Width, backgroundImage.Height, GraphicsUnit.Pixel, attributes1 );
                attributes1.Dispose();
            }
        }


        internal static Rectangle CalculateBackgroundImageRectangle( Rectangle bounds, Image backgroundImage, ImageLayout imageLayout )
        {
            Rectangle rectangle1 = bounds;
            if (backgroundImage != null)
            {
                switch (imageLayout)
                {
                    case ImageLayout.None:
                        rectangle1.Size = backgroundImage.Size;
                        return rectangle1;

                    case ImageLayout.Tile:
                        return rectangle1;

                    case ImageLayout.Center:
                        {
                            rectangle1.Size = backgroundImage.Size;
                            Size size1 = bounds.Size;
                            if (size1.Width > rectangle1.Width)
                            {
                                rectangle1.X = ( size1.Width - rectangle1.Width ) / 2;
                            }
                            if (size1.Height > rectangle1.Height)
                            {
                                rectangle1.Y = ( size1.Height - rectangle1.Height ) / 2;
                            }
                            return rectangle1;
                        }
                    case ImageLayout.Stretch:
                        rectangle1.Size = bounds.Size;
                        return rectangle1;

                    case ImageLayout.Zoom:
                        {
                            Size size2 = backgroundImage.Size;
                            float single1 = ( (float)bounds.Width ) / ( (float)size2.Width );
                            float single2 = ( (float)bounds.Height ) / ( (float)size2.Height );
                            if (single1 < single2)
                            {
                                rectangle1.Width = bounds.Width;
                                rectangle1.Height = (int)( ( size2.Height * single1 ) + 0.5 );
                                if (bounds.Y >= 0)
                                {
                                    rectangle1.Y = ( bounds.Height - rectangle1.Height ) / 2;
                                }
                                return rectangle1;
                            }
                            rectangle1.Height = bounds.Height;
                            rectangle1.Width = (int)( ( size2.Width * single2 ) + 0.5 );
                            if (bounds.X >= 0)
                            {
                                rectangle1.X = ( bounds.Width - rectangle1.Width ) / 2;
                            }
                            return rectangle1;
                        }
                }
            }
            return rectangle1;
        }

        //p.p.  28.08.07
         Point downPoint = Point.Empty;
        private bool enableResizing = true;
        const int WM_NCLBUTTONDOWN = 0xa1;
         const int HTLEFT = 10;
         const int HTRIGHT = 11;
         const int HTTOP = 12;
         const int HTTOPLEFT = 13;
         const int HTTOPRIGHT = 14;
         const int HTBOTTOM = 15;
         const int HTBOTTOMLEFT = 16;
         const int HTBOTTOMRIGHT = 17;


        [DllImport( "user32.dll", CharSet = CharSet.Auto, ExactSpelling = true )]
        public static extern bool ReleaseCapture();

        [DllImport( "user32.dll", CharSet = CharSet.Auto )]
        public static extern IntPtr SendMessage( HandleRef hWnd, int Msg, int wParam, IntPtr lParam );

        protected override void OnMouseDown( MouseEventArgs e )
        {
            base.OnMouseDown( e );
            this.downPoint = e.Location;
        }

        protected override void OnMouseUp( MouseEventArgs e )
        {
            base.OnMouseUp( e );
            Cursor.Current = Cursors.Default;
        }

        protected override void OnMouseMove( MouseEventArgs e )
        {
            if (!this.EnableResizing)
            {
                return;
            }

            base.OnMouseMove( e );

            Form form = this.FindForm();
            if (form == null)
            {
                return;
            }
                        
            int wParam = 0;
            if (this.Orientation == Orientation.Vertical)
            {
                Cursor.Current = Cursors.SizeWE;
                if ((this.Anchor & AnchorStyles.Left) != 0 ||
                    this.Dock == DockStyle.Left)
                {
                    wParam = HTLEFT;//left panel

                    if (e.Y < 7)
                    {
                        Cursor.Current = Cursors.SizeNWSE;
                        wParam = HTTOPLEFT;
                    }
                    if (e.Y > this.Size.Height - 7)
                    {
                        Cursor.Current = Cursors.SizeNESW;
                        wParam = HTBOTTOMLEFT;
                    }
                }
                else
                {
                    wParam = HTRIGHT;//right panel
                    if (e.Y < 7)
                    {
                        Cursor.Current = Cursors.SizeNWSE;
                        wParam = HTTOPRIGHT;
                    }
                    if (e.Y > this.Size.Height - 7)
                    {
                        Cursor.Current = Cursors.SizeNESW;
                        wParam = HTBOTTOMRIGHT;
                    }
                }
            }
            else
            {
                Cursor.Current = Cursors.SizeNS;
                if ((this.Anchor & AnchorStyles.Bottom) != 0 ||
                    this.Dock == DockStyle.Bottom)
                {
                    wParam = HTBOTTOM; //bottom panel

                    if (e.X < 7)
                    {
                        Cursor.Current = Cursors.SizeNESW;
                        wParam = HTBOTTOMLEFT;
                    }
                    if (e.X > this.Size.Width - 7)
                    {
                        Cursor.Current = Cursors.SizeNWSE;
                        wParam = HTBOTTOMRIGHT;
                    }
                }
                else
                {
                    wParam = HTTOP; //top panel                    

                    if (e.X < 7)
                    {
                        Cursor.Current = Cursors.SizeNESW;
                        wParam = HTTOPLEFT;
                    }
                    if (e.X > this.Size.Width - 7)
                    {
                        Cursor.Current = Cursors.SizeNWSE;
                        wParam = HTTOPRIGHT;
                    }
                }
            }
            if (e.Button == MouseButtons.Left && downPoint != e.Location)//&& e.X < this.Size.Width)
            {
                ReleaseCapture();
                SendMessage( new HandleRef( this, form.Handle ), WM_NCLBUTTONDOWN, wParam, IntPtr.Zero );
            }
        }
        //end add

    }
}
