// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool Xbim.CodeGeneration 
//  
//     Changes to this file may cause incorrect behaviour and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------

using Xbim.Ifc4.Interfaces;
using System.Collections.Generic;
using System.Linq;
using Xbim.Common;

//## Custom using statements
using Xbim.Ifc4.MeasureResource;
//##

// ReSharper disable once CheckNamespace
namespace Xbim.Ifc4x3.ProductExtension
{
	public partial class @IfcBuildingStorey : IIfcBuildingStorey
	{

		[CrossSchemaAttribute(typeof(IIfcBuildingStorey), 10)]
		Ifc4.MeasureResource.IfcLengthMeasure? IIfcBuildingStorey.Elevation 
		{ 
			get
			{
				if (!Elevation.HasValue) return null;
				return new Ifc4.MeasureResource.IfcLengthMeasure(Elevation.Value);
			} 
			set
			{
				Elevation = value.HasValue ? 
					new MeasureResource.IfcLengthMeasure(value.Value) :  
					 new MeasureResource.IfcLengthMeasure?() ;
				
			}
		}
	//## Custom code
		/// <summary>
		/// Returns the site (if any) that contains this building, null if the building is not decomposing a site
		/// </summary>
		/// <returns></returns>
		public IIfcSite Site
		{
			get
			{
				return Decomposes.SelectMany(r => r.RelatedObjects).OfType<IIfcSite>().FirstOrDefault();
			}
		}

		/// <summary>
		/// Returns the buidlings that decompose this building
		/// </summary>
		/// <returns></returns>
		public IEnumerable<IIfcBuilding> Buildings
		{
			get
			{
				return IsDecomposedBy.SelectMany(s => s.RelatedObjects).OfType<IIfcBuilding>();
			}
		}

		/// <summary>
		/// Returns all spaces that are sub-spaces of this building
		/// </summary>
		/// <returns></returns>
		public IEnumerable<IIfcSpace> Spaces
		{
			get
			{
				return IsDecomposedBy.SelectMany(s => s.RelatedObjects).OfType<IIfcSpace>();
			}
		}



		/// <summary>
		/// Returns the building storeys for this floor  
		/// </summary>
		/// <returns></returns>
		public IEnumerable<IIfcBuildingStorey> BuildingStoreys
		{
            get
            {
                var storeys = IsDecomposedBy.SelectMany(s => s.RelatedObjects).OfType<IfcBuildingStorey>().ToList();
                storeys.Sort(CompareStoreysByElevation);
                return storeys;
            }
        }
		/// <summary>
		/// Returns the Gross Floor Area, if the element base quantity GrossFloorArea is defined
		/// </summary>
		/// <returns></returns>
		public IfcAreaMeasure? GrossFloorArea
		{
			get
			{
				var qArea = GetQuantity<IIfcQuantityArea>("BaseQuantities", "GrossFloorArea") ??
							GetQuantity<IIfcQuantityArea>("GrossFloorArea");
				return qArea != null ? (IfcAreaMeasure?)qArea.AreaValue : null;
			}
		}

		public IfcLengthMeasure? TotalHeight
		{
			get
			{
				var qLen = GetQuantity<IIfcQuantityLength>("BaseQuantities", "TotalHeight") ??
						   GetQuantity<IIfcQuantityLength>("TotalHeight");
				return qLen != null ? (IfcLengthMeasure?)qLen.LengthValue : null;
			}
		}

		/// <summary>
		/// Returns the first quantity in the property set pSetName of name qName
		/// </summary>
		/// <typeparam name="TQType"></typeparam>
		/// <param name="pSetName"></param>
		/// <param name="qName"></param>
		/// <returns></returns>
		public TQType GetQuantity<TQType>(string pSetName, string qName) where TQType : IIfcPhysicalQuantity
		{
			var propSets = IsDefinedBy.SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions);
			var rel = propSets.FirstOrDefault(r => r is IfcElementQuantity && r.Name == pSetName);
			if (rel == null) return default(TQType);
			var eQ = rel as IfcElementQuantity;
			return eQ == null ? default(TQType) : eQ.Quantities.OfType<TQType>().FirstOrDefault(q => q.Name == qName);
		}

		/// <summary>
		/// Returns the first quantity that matches the quantity name
		/// </summary>
		/// <typeparam name="TQType"></typeparam>
		/// <param name="qName"></param>
		/// <returns></returns>
		public TQType GetQuantity<TQType>(string qName) where TQType : IIfcPhysicalQuantity
		{
			var qSets = IsDefinedBy.SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions).OfType<IIfcElementQuantity>();
			return qSets.SelectMany(qset => qset.Quantities).OfType<TQType>().FirstOrDefault(q => q.Name == qName);
		}

        internal static int CompareStoreysByElevation(IfcBuildingStorey x, IfcBuildingStorey y)
        {
            double a = x.Elevation ?? 0;
            double b = y.Elevation ?? 0;
            return a.CompareTo(b);
        }
        //##
    }
}