// 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.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using mshtml;
using OpenLiveWriter.Api;
using OpenLiveWriter.CoreServices;
using OpenLiveWriter.CoreServices.Diagnostics;
using OpenLiveWriter.Extensibility.BlogClient;
using OpenLiveWriter.Extensibility.ImageEditing;
using OpenLiveWriter.PostEditor.PostHtmlEditing.ImageEditing.Decorators;

namespace OpenLiveWriter.PostEditor.PostHtmlEditing
{
	/// <summary>
	/// Implements an ImageFilter
	/// </summary>
	internal class ImageFilterDecoratorAdapter : ImageDecoratorContext
	{
		Bitmap _originalImage;
		Bitmap _currImage;
		IProperties _currSettings;
		ImagePropertiesInfo _imageInfo;
		ImageDecoratorsList _decoratorsList;
		ImageEmbedType _embedType;
        IEditorOptions _editorOptions;

		private ImageFilterDecoratorAdapter(ImagePropertiesInfo imageInfo, ImageEmbedType embedType, ImageDecoratorInvocationSource invocationSource, IEditorOptions editorOptions)
		{
			_decoratorsList = imageInfo.ImageDecorators;
			_imageInfo = imageInfo;
			_embedType = embedType;
			_invocationSource = invocationSource;
            _editorOptions = editorOptions;
		}

		public static ImageFilter CreateImageDecoratorsFilter(ImagePropertiesInfo imageInfo, ImageEmbedType embedType, ImageDecoratorInvocationSource invocationSource, IEditorOptions editorOptions)
		{
            return new ImageFilter(new ImageFilterDecoratorAdapter(imageInfo, embedType, invocationSource, editorOptions).ApplyImageDecorators);
		}

		public Bitmap ApplyImageDecorators(Bitmap bitmap)
		{
			_currImage = bitmap;
			_originalImage = bitmap;

		    bool borderNeedsReset = true;
            foreach (ImageDecorator decorator in _decoratorsList)
            {
                ApplyImageDecorator(decorator, _currImage, ref borderNeedsReset);
            }

		    //update the rotation and size info in the image properties
			if(_embedType == ImageEmbedType.Embedded)
			{
//                if (borderNeedsReset)
//                    BorderMargin = ImageBorderMargin.Empty;

                if (!ImageHelper2.IsAnimated(_currImage))
                {
                    Size currImageSize = _currImage.Size;

                    //update the inline image size (don't forget to remove size added by borders)
                    ImageBorderMargin borderMargin = BorderMargin;
                    Size borderlessImageSize = new Size(
                        currImageSize.Width - borderMargin.Width,
                        currImageSize.Height - borderMargin.Height);
                    _imageInfo.InlineImageSize = borderlessImageSize;
                }
			}
			else
			{
				_imageInfo.LinkTargetImageSize = _currImage.Size;
			}

			_originalImage = null;
			return _currImage;
		}

		private void ApplyImageDecorator(ImageDecorator decorator, Bitmap bitmap, ref bool borderNeedsReset)
		{
            if (_embedType != ImageEmbedType.Embedded
                && (decorator.IsBorderDecorator || decorator.Id == TiltDecorator.Id))
            {
                return;
            }

            if (borderNeedsReset 
                && _embedType == ImageEmbedType.Embedded
                && (decorator.IsBorderDecorator || decorator.Id == TiltDecorator.Id))
            {
                borderNeedsReset = false;
                //BorderMargin = ImageBorderMargin.Empty;
            }

		    try
			{
                using (ApplicationPerformance.LogEvent("ApplyDecorator: " + decorator.DecoratorName))
				using (new WaitCursor())
				{
					_currImage = bitmap;
					_currSettings = _decoratorsList.GetImageDecoratorSettings(decorator);
					decorator.Decorate(this);
				}
			}
			catch(Exception e)
			{
				Trace.Fail(String.Format(CultureInfo.InvariantCulture, "Failed to apply image decorator [{0}]: {1}", decorator.DecoratorName, e.ToString()));
			}
		}

		public Bitmap Image
		{
			get { return _currImage; }
			set
			{
                if (!ReferenceEquals(_currImage, value))
                {
                    if (_originalImage != _currImage)
                    {
                        //then the current image was generated by a decorator, and won't get disposed
                        //by the caller, so dispose it automatically;
                        _currImage.Dispose();
                    }
                    _currImage = value;
                }
			}
		}

		public IProperties Settings
		{
			get { return _currSettings; }
		}

	    public IEditorOptions EditorOptions
	    {
            get { return _editorOptions; }
	    }

	    public ImageEmbedType ImageEmbedType
		{
			get{ return _embedType;}
		}

		public IHTMLElement ImgElement
		{
			get { return _imageInfo.ImgElement; }
		}

		public ImageDecoratorInvocationSource InvocationSource
		{
			get { return _invocationSource; }
		}
		private ImageDecoratorInvocationSource _invocationSource;

	    public RotateFlipType ImageRotation
		{
			get
			{
				return _imageInfo.ImageRotation;
			}
		}

		public Uri SourceImageUri
		{
			get { return _imageInfo.ImageSourceUri; }
		}

	    public float? EnforcedAspectRatio
	    {
            get { return _decoratorsList.EnforcedAspectRatio; }
	    }

	    public ImageBorderMargin BorderMargin
		{
			get { return _imageInfo.InlineImageBorderMargin; }
			set { _imageInfo.InlineImageBorderMargin = value; }
		}
	}
}
