text: ﻿using System;
  using static Xamarin.Forms.Platform.GTK.Platform;
  
  namespace Xamarin.Forms.Platform.GTK.Cells
  {
  	internal class ViewCell : CellBase
  	{
  		private WeakReference<IVisualElementRenderer> _rendererRef;
  		private Gdk.Rectangle _lastAllocation;
  
  		protected override void OnSizeAllocated(Gdk.Rectangle allocation)
  		{
  			base.OnSizeAllocated(allocation);
  
  			if (_lastAllocation != allocation)
  			{
  				_lastAllocation = allocation;
  
  				var viewCell = Cell as Xamarin.Forms.ViewCell;
  				var view = viewCell.View;
  
  				if (view == null)
  				{
  					return;
  				}
  
  				double width = allocation.Width;
  				double height = DesiredHeight > 0
  								? DesiredHeight
  								: Cell.RenderHeight > 0
  									? Cell.RenderHeight
  									: GetHeightMeasure(viewCell, allocation);
  
  				Layout.LayoutChildIntoBoundingRegion(view, new Rectangle(0, 0, width, height));
  
  				if (_rendererRef == null)
  					return;
  
  				IVisualElementRenderer renderer;
  				if (_rendererRef.TryGetTarget(out renderer))
  				{
  					renderer.Container.WidthRequest = (int)width;
  				}
  			}
  		}
  
  		private double GetHeightMeasure(Xamarin.Forms.ViewCell viewCell, Gdk.Rectangle allocation)
  		{
  			var request = viewCell.View.Measure(allocation.Width, double.PositiveInfinity, MeasureFlags.IncludeMargins);
  
  			return request.Request.Height;
  		}
  
  		public override void Destroy()
  		{
  			IVisualElementRenderer renderer;
  			if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null)
  			{
  				_rendererRef = null;
  			}
  
  			base.Destroy();
  		}
  
  		protected override void UpdateCell()
  		{
  			var viewCell = Cell as Xamarin.Forms.ViewCell;
  
  			if (viewCell != null)
  				Device.BeginInvokeOnMainThread(viewCell.SendDisappearing);
  
  			Device.BeginInvokeOnMainThread(viewCell.SendAppearing);
  
  			IVisualElementRenderer renderer;
  			if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer))
  				renderer = GetNewRenderer();
  			else
  			{
  				if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element))
  					renderer.Element.ClearValue(Platform.RendererProperty);
  
  				var type = Internals.Registrar.Registered.GetHandlerType(viewCell.View.GetType());
  				if (renderer.GetType() == type || (renderer is DefaultRenderer && type == null))
  					renderer.SetElement(viewCell.View);
  				else
  				{
  					renderer = GetNewRenderer();
  				}
  			}
  
  			Platform.SetRenderer(viewCell.View, renderer);
  		}
  
  		private IVisualElementRenderer GetNewRenderer()
  		{
  			var viewCell = Cell as Xamarin.Forms.ViewCell;
  
  			if (viewCell.View == null)
  			{
  				return null;
  			}
  
  			var newRenderer = Platform.CreateRenderer(viewCell.View);
  
  			_rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer);
  			Add(newRenderer.Container);
  
  			return newRenderer;
  		}
  	}
  }
  