// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

namespace Microsoft.Data.Entity.Design.Model
{
    using System;
    using System.Collections.Generic;
    using System.Xml.Linq;

    internal abstract class EFNameableItem : EFNormalizableItem
    {
        internal const string AttributeName = "Name";

        private DefaultableValue<string> _localName;

        internal EFNameableItem(EFContainer parent, XElement element)
            :
                base(parent, element)
        {
        }

        // we unfortunately get a warning from the compiler when we use the "base" keyword in "iterator" types generated by using the
        // "yield return" keyword.  By adding this method, I was able to get around this.  Unfortunately, I wasn't able to figure out
        // a way to implement this once and have derived classes share the implementation (since the "base" keyword is resolved at 
        // compile-time and not at runtime.
        private IEnumerable<EFObject> BaseChildren
        {
            get { return base.Children; }
        }

        internal override IEnumerable<EFObject> Children
        {
            get
            {
                foreach (var efobj in BaseChildren)
                {
                    yield return efobj;
                }
                yield return LocalName;
            }
        }

        internal override void Rename(string newName)
        {
            if (string.Compare(newName, GetNameAttribute().Value, StringComparison.CurrentCulture) != 0)
            {
                GetNameAttribute().Value = newName;
            }
        }

        internal override DefaultableValue<string> GetNameAttribute()
        {
            return LocalName;
        }

        internal virtual DefaultableValue<string> LocalName
        {
            get { return _localName ?? (_localName = new LocalNameDefaultableValue(this)); }
        }

        private class LocalNameDefaultableValue : DefaultableValue<string>
        {
            internal LocalNameDefaultableValue(EFElement parent)
                :
                    base(parent, EFNameableItem.AttributeName)
            {
            }

            internal override string AttributeName
            {
                get { return EFNameableItem.AttributeName; }
            }

            public override string DefaultValue
            {
                get { return String.Empty; }
            }
        }

        protected override void PreParse()
        {
            ClearEFObject(_localName);
            _localName = null;
            base.PreParse();
        }

        public override IValueProperty<string> Name
        {
            get
            {
                var n = this;
                var dv = n.LocalName;
                return dv;
            }
        }

#if DEBUG
        internal override ICollection<string> MyAttributeNames()
        {
            var s = base.MyAttributeNames();
            s.Add(AttributeName);
            return s;
        }
#endif
    }

    internal class EFNameableItemComparer : IComparer<EFNameableItem>
    {
        //used to sort nameable items
        public int Compare(EFNameableItem left, EFNameableItem right)
        {
            var leftName = left.LocalName.Value;
            var rightName = right.LocalName.Value;
            // sorted in case insensitive alphabetical order.
            return String.Compare(leftName, rightName, StringComparison.CurrentCultureIgnoreCase);
        }
    }
}
