// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for details.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
using System.Net;
using System.Windows.Forms;
using OpenLiveWriter.ApplicationFramework;
using OpenLiveWriter.Controls;
using OpenLiveWriter.CoreServices;
using OpenLiveWriter.CoreServices.Layout;
using OpenLiveWriter.Interop.Windows;
using OpenLiveWriter.Localization;
using OpenLiveWriter.Localization.Bidi;
using OpenLiveWriter.PostEditor.PostHtmlEditing;

namespace OpenLiveWriter.PostEditor.ImageInsertion
{
    /// <summary>
    /// Summary description for WebImageControl.
    /// </summary>
    public class WebImageSource : InsertImageSource
    {
        private Label _labelOne;
        private TextBoxWithPaste _webImageUrl;
        private BorderControl _pictureBorder;
        private PictureBox _previewBox;
        private Button _previewButton;
        private Label _labelSize;
        private Label _fileSize;
        private bool _selected = false;
        UserControl _control;
        private int _width;
        private int _height;

        private const int WebImageUrlPadding = 6;
        private const int SizeLabelPadding = 6;

        public void Init(int width, int height)
        {
            _width = width;
            _height = height;
        }

        public string TabName
        {
            get
            {
                return Res.Get(StringId.InsertImageInsertFromWeb);
            }
        }

        public Bitmap TabBitmap
        {
            get
            {
                return ResourceHelper.LoadAssemblyResourceBitmap("ImageInsertion.Images.TabInsertFromWeb.png");
            }
        }

        public UserControl ImageSelectionControls
        {
            get
            {
                if (_control == null)
                {
                    _control = new UserControl();
                    _control.Location = new Point(0, 0);
                    _control.Size = new Size(_width, _height);
                    _control.Load += new EventHandler(_control_Load);
                    _control.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
                    _control.Font = Res.DefaultFont;

                    _labelOne = new Label();
                    _labelOne.FlatStyle = FlatStyle.System;
                    _labelOne.Text = Res.Get(StringId.InsertImageImageUrl);
                    _labelOne.Location = new Point(10, 13);
                    _labelOne.Size = new Size(87, 15);
                    _labelOne.Anchor = AnchorStyles.Left | AnchorStyles.Top;

                    _webImageUrl = new TextBoxWithPaste();
                    _webImageUrl.Location = new Point(10, 31);
                    _webImageUrl.Size = new Size(377, 20);
                    _webImageUrl.Name = "imageUrl";
                    _webImageUrl.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
                    _webImageUrl.OnPaste += new TextBoxWithPaste.OnPasteEventHandler(this._imageUrl_Paste);
                    _webImageUrl.RightToLeft = RightToLeft.No;
                    if (BidiHelper.IsRightToLeft)
                        _webImageUrl.TextAlign = HorizontalAlignment.Right;

                    _previewButton = new Button();
                    _previewButton.Location = new Point(395, 31);
                    _previewButton.Size = new Size(75, 23);
                    _previewButton.FlatStyle = FlatStyle.System;
                    _previewButton.Text = Res.Get(StringId.InsertImagePreviewButton);
                    _previewButton.Name = "previewButton";
                    _previewButton.Click += new EventHandler(_previewButton_Click);
                    _previewButton.Anchor = AnchorStyles.Right | AnchorStyles.Top;

                    _previewBox = new PictureBox();
                    _previewBox.BackColor = Color.White;
                    _previewBox.BorderStyle = BorderStyle.None;
                    _previewBox.SizeMode = PictureBoxSizeMode.CenterImage;
                    _previewBox.Name = "previewBox";

                    _pictureBorder = new BorderControl();
                    _pictureBorder.Location = new Point(10, 59);
                    _pictureBorder.Size = new Size(460, 283);
                    _pictureBorder.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top |
                                            AnchorStyles.Bottom;
                    _pictureBorder.Control = _previewBox;

                    _labelSize = new Label();
                    _labelSize.FlatStyle = FlatStyle.System;
                    _labelSize.Text = Res.Get(StringId.InsertImageSize);
                    _labelSize.Size = new Size(35, 15);
                    _labelSize.Location = new Point(10, 347);
                    _labelSize.Anchor = AnchorStyles.Left | AnchorStyles.Bottom;

                    _fileSize = new Label();
                    _fileSize.FlatStyle = FlatStyle.System;
                    _fileSize.Text = "";
                    _fileSize.Size = new Size(438, 15);
                    _fileSize.Location = new Point(51, 347);
                    _fileSize.Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right;

                    _control.Controls.Add(_labelOne);
                    _control.Controls.Add(_webImageUrl);
                    _control.Controls.Add(_previewButton);
                    _control.Controls.Add(_pictureBorder);
                    _control.Controls.Add(_labelSize);
                    _control.Controls.Add(_fileSize);
                    _control.Name = "WebImageSource";
                    _control.RightToLeft = BidiHelper.IsRightToLeft ? RightToLeft.Yes : RightToLeft.No;
                }
                return _control;
            }
        }

        private void _control_Load(object sender, EventArgs e)
        {
            LayoutHelper.AutoFitLabels(_labelSize);

            DisplayHelper.AutoFitSystemLabel(_labelOne, _labelOne.Width, int.MaxValue);
            DisplayHelper.AutoFitSystemButton(_previewButton, 0, int.MaxValue);

            if (_control.RightToLeft == RightToLeft.Yes)
            {
                _webImageUrl.Left = _previewButton.Right + (int)DisplayHelper.ScaleX(WebImageUrlPadding);
                _webImageUrl.Width = _pictureBorder.Right - _previewButton.Right - (int)DisplayHelper.ScaleX(WebImageUrlPadding);

                _fileSize.Left = _pictureBorder.Left;
                _fileSize.Width = _labelSize.Left - _fileSize.Left - SizeLabelPadding;
            }
            else
            {
                _webImageUrl.Left = _pictureBorder.Left;
                _webImageUrl.Width = _previewButton.Left - _webImageUrl.Left - (int)DisplayHelper.ScaleX(WebImageUrlPadding);

                _fileSize.Left = _labelSize.Right + SizeLabelPadding;
                _fileSize.Width = _pictureBorder.Right - _fileSize.Left;
            }

            BidiHelper.RtlLayoutFixup(_control);

            _webImageUrl.Select();
        }

        private void _imageUrl_Paste(object sender, TextBoxWithPaste.PasteEventArgs eventArgs)
        {
            //special case...image on clipboard
            if (_webImageUrl.Text.Trim() == String.Empty)
            {
                DataObjectMeister dataObject = new DataObjectMeister(Clipboard.GetDataObject());
                if (dataObject.HTMLData != null && dataObject.HTMLData.OnlyImagePath != null)
                {
                    _webImageUrl.Text = dataObject.HTMLData.OnlyImagePath;
                }
            }
            PopulatePreviewBox();
            _webImageUrl.SelectAll();
        }

        public void Repaint(Size newSize)
        {
            _control.Size = newSize;

        }

        public string SourceImageLink
        {
            get { return FileName; }
        }

        public void TabSelected()
        {
            _webImageUrl.Focus();
        }

        public event EventHandler OnSelectionMade;

        public string FileName
        {
            get
            {
                return UrlHelper.FixUpUrl(_webImageUrl.Text);
            }
        }

        public bool ValidateSelection()
        {
            if (!UrlHelper.IsUrl(UrlHelper.FixUpUrl(_webImageUrl.Text)))
            {
                DisplayMessage.Show(MessageId.InvalidWebImage);
                _webImageUrl.Focus();
                return false;
            }
            return true;
        }

        public bool HandleEnter(int cmdId)
        {
            int previewButtonId = (int)User32.GetDlgCtrlID(_previewButton.Handle) & 0xFFFF;
            if (previewButtonId == cmdId)
            {
                _previewButton.PerformClick();
                return true;
            }
            return false;
        }

        public bool Selected
        {
            get
            {
                return _selected;
            }
            set
            {
                _selected = value;
            }
        }

        private void _previewButton_Click(object sender, EventArgs e)
        {
            PopulatePreviewBox();
        }

        private void PopulatePreviewBox()
        {
            string imageUrl = _webImageUrl.Text.Trim();
            if (imageUrl != String.Empty && UrlHelper.IsUrl(imageUrl))
            {
                using (new WaitCursor())
                {
                    try
                    {
                        HttpWebResponse response = HttpRequestHelper.SendRequest(UrlHelper.FixUpUrl(imageUrl));
                        Bitmap webImage;
                        using (Stream responseStream = response.GetResponseStream())
                            webImage = new Bitmap(StreamHelper.CopyToMemoryStream(responseStream));

                        SetPreviewPicture(webImage, imageUrl);

                        if (OnSelectionMade != null)
                            OnSelectionMade(this, new EventArgs());

                    }
                    catch (Exception)
                    {
                        _previewBox.Image = null;
                        DisplayMessage.Show(MessageId.NoPreviewAvailable);
                        _webImageUrl.Focus();
                    }
                }
            }
            else
            {
                _previewBox.Image = null;
                DisplayMessage.Show(MessageId.NoPreviewAvailable);
                _webImageUrl.Focus();
            }
        }

        private void SetPreviewPicture(Bitmap image, string filename)
        {
            int maxWidth = _previewBox.Width - 2;
            int maxHeight = _previewBox.Height - 2;
            bool scaled = true;
            int currentWidth = image.Width;
            int currentHeight = image.Height;
            double ratio = 1.00;
            //if height and width are too big
            if (currentWidth > maxWidth && currentHeight > maxHeight)
            {
                //size according to the one that is more off of the available area
                if ((maxWidth / currentWidth) < (maxHeight / currentHeight))
                {
                    ratio = (double)maxWidth / (double)currentWidth;
                }
                else
                {
                    ratio = (double)maxHeight / (double)currentHeight;
                }
            }
            //if just width
            else if (currentWidth > maxWidth)
            {
                ratio = (double)maxWidth / (double)currentWidth;
            }
            //if just height
            else if (currentHeight > maxHeight)
            {
                ratio = (double)maxHeight / (double)currentHeight;
            }
            //else fine
            else
            {
                scaled = false;
            }

            ImageFormat format;
            string fileExt;
            ImageHelper2.GetImageFormat(filename, out fileExt, out format);
            int newWidth = (int)(currentWidth * ratio);
            int newHeight = (int)(currentHeight * ratio);

            Bitmap newImage = ImageHelper2.CreateResizedBitmap(image, newWidth, newHeight, format);

            //if image is small enough, add border
            if (newWidth <= maxWidth && newHeight <= maxHeight)
            {
                Bitmap borderPic = new Bitmap(newWidth + 2, newHeight + 2);
                //Get a graphics object for it
                using (Graphics g = Graphics.FromImage(borderPic))
                {
                    g.TextRenderingHint = TextRenderingHint.AntiAlias;

                    int R = SystemColors.Control.R;
                    int G = SystemColors.Control.G;
                    int B = SystemColors.Control.B;
                    Color dark = Color.FromArgb((int)(R * 0.9), (int)(G * 0.9), (int)(B * 0.9));
                    //draw the border
                    g.FillRectangle(new SolidBrush(dark), new Rectangle(0, 0, borderPic.Width, 1));
                    g.FillRectangle(new SolidBrush(dark), new Rectangle(0, borderPic.Height - 1, borderPic.Width, 1));
                    g.FillRectangle(new SolidBrush(dark), new Rectangle(0, 0, 1, borderPic.Height));
                    g.FillRectangle(new SolidBrush(dark), new Rectangle(borderPic.Width - 1, 0, 1, borderPic.Height));

                    //draw our image back in the middle
                    g.DrawImage(newImage, new Rectangle(1, 1, newWidth, newHeight), 0, 0, newWidth, newHeight, GraphicsUnit.Pixel);
                }
                _previewBox.Image = borderPic;
            }
            else
            {
                _previewBox.Image = newImage;
            }

            string picsize;
            if (!scaled)
                picsize = MakeDimensions(currentWidth, currentHeight);
            else
            {
                picsize = string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.InsertImageDimensionsFormatScaled),
                                  MakeDimensions(currentWidth, currentHeight));
            }
            _fileSize.Text = picsize;
        }

        private static string MakeDimensions(int width, int height)
        {
            return string.Format(CultureInfo.CurrentCulture, Res.Get(StringId.InsertImageDimensionsFormat), width, height);
        }
    }
}