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

namespace System.Data.Entity.Core.Query.InternalTrees
{
    using System.Data.Entity.Core.Metadata.Edm;
    using System.Data.Entity.Utilities;

    /// <summary>
    ///     All scalars fall into this category
    /// </summary>
    internal abstract class ScalarOp : Op
    {
        #region private state

        private TypeUsage m_type;

        #endregion

        #region constructors

        /// <summary>
        ///     Default constructor
        /// </summary>
        /// <param name="opType"> kind of Op </param>
        /// <param name="type"> type of value produced by this Op </param>
        internal ScalarOp(OpType opType, TypeUsage type)
            : this(opType)
        {
            DebugCheck.NotNull(type);
            m_type = type;
        }

        protected ScalarOp(OpType opType)
            : base(opType)
        {
        }

        #endregion

        #region public methods

        /// <summary>
        ///     ScalarOp
        /// </summary>
        internal override bool IsScalarOp
        {
            get { return true; }
        }

        /// <summary>
        ///     Two scalarOps are equivalent (usually) if their OpTypes and types are the
        ///     same. Obviously, their arguments need to be equivalent as well - but that's
        ///     checked elsewhere
        /// </summary>
        /// <param name="other"> The other Op to compare against </param>
        /// <returns> true, if the Ops are indeed equivalent </returns>
        internal override bool IsEquivalent(Op other)
        {
            return (other.OpType == OpType && TypeSemantics.IsStructurallyEqual(Type, other.Type));
        }

        /// <summary>
        ///     Datatype of result
        /// </summary>
        internal override TypeUsage Type
        {
            get { return m_type; }
            set { m_type = value; }
        }

        /// <summary>
        ///     Is this an Aggregate
        /// </summary>
        internal virtual bool IsAggregateOp
        {
            get { return false; }
        }

        #endregion
    }
}
