﻿//---------------------------------------------------------------------
// <copyright file="LinqNewExpression.cs" company="Microsoft">
//      Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

namespace Microsoft.Test.Taupo.Query.Contracts.Linq.Expressions
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;

    /// <summary>
    /// Expression node representing the creation of anonymous type in a Linq query.
    /// </summary>
    public class LinqNewExpression : QueryExpression
    {
        internal LinqNewExpression(IEnumerable<string> memberNames, IEnumerable<QueryExpression> members, QueryType type)
            : base(type)
        {
            this.MemberNames = memberNames.ToList().AsReadOnly();
            this.Members = members.ToList().AsReadOnly();
        }

        /// <summary>
        /// Gets the list of property member names.
        /// </summary>
        public ReadOnlyCollection<string> MemberNames { get; private set; }

        /// <summary>
        /// Gets the list of members.
        /// </summary>
        public ReadOnlyCollection<QueryExpression> Members { get; private set; }

        /// <summary>
        /// Returns string that represents the expression.
        /// </summary>
        /// <returns>String representation for the expression.</returns>
        /// <remarks>This functionality is for debug purposes only.</remarks>
        public override string ToString()
        {
            string anonymousBody = string.Join(", ", this.MemberNames.Select((n, i) => string.Format(CultureInfo.InvariantCulture, "{0} = {1}", n, this.Members[i])).ToArray());

            return string.Format(CultureInfo.InvariantCulture, "new {{ {0} }}", anonymousBody);
        }

        /// <summary>
        /// The Accept method used to support the double-dispatch visitor pattern with a visitor that returns a result.
        /// </summary>
        /// <typeparam name="TResult">The result type returned by the visitor.</typeparam>
        /// <param name="visitor">The visitor that is visiting this expression.</param>
        /// <returns>The result of visiting this expression.</returns>
        public override TResult Accept<TResult>(ICommonExpressionVisitor<TResult> visitor)
        {
            return ((ILinqExpressionVisitor<TResult>)visitor).Visit(this);
        }
    }
}
