// Copyright (C) 2009-2024 Xtensive LLC.
// This code is distributed under MIT license terms.
// See the License.txt file in the project root for more information.

using System;
using System.Collections.Generic;

namespace Xtensive.Sql.Dml
{
  [Serializable]
  public class SqlJoinedTable : SqlTable
  {
    private SqlJoinExpression joinExpression;

    /// <summary>
    /// Gets the join expression.
    /// </summary>
    /// <value>The join expression.</value>
    public SqlJoinExpression JoinExpression
    {
      get { return joinExpression; }
    }

    /// <summary>
    /// Gets or sets the aliased columns.
    /// </summary>
    /// <value>Aliased columns.</value>
    public SqlColumnCollection AliasedColumns { get; private set; }

    internal override object Clone(SqlNodeCloneContext context) =>
      context.NodeMapping.TryGetValue(this, out var clone)
        ? clone
        : context.NodeMapping[this] = new SqlJoinedTable((SqlJoinExpression) joinExpression.Clone(context)) {
            AliasedColumns = new SqlColumnCollection(new List<SqlColumn>(AliasedColumns))
          };

    public override void AcceptVisitor(ISqlVisitor visitor)
    {
      joinExpression.AcceptVisitor(visitor);
    }

    /// <inheritdoc/>
    public override IEnumerator<SqlTable> GetEnumerator()
    {
      return joinExpression.GetEnumerator();
    }


    // Constructor

    internal SqlJoinedTable(SqlJoinExpression joinExpression)
      : this(joinExpression, joinExpression.Left.Columns, joinExpression.Right.Columns)
    {
    }

    internal SqlJoinedTable(SqlJoinExpression joinExpression, IReadOnlyList<SqlColumn> leftColumns, IReadOnlyList<SqlColumn> rightColumns)
    {
      this.joinExpression = joinExpression;
      var allLeftColumns = joinExpression.Left.Columns;
      var allRightColumns = joinExpression.Right.Columns;

      var joinedColumns = new List<SqlTableColumn>(allLeftColumns.Count + allRightColumns.Count);
      joinedColumns.AddRange(allLeftColumns);
      joinedColumns.AddRange(allRightColumns);
      columns = new SqlTableColumnCollection(joinedColumns);

      var aliasedColumns = new List<SqlColumn>(leftColumns.Count + rightColumns.Count);
      aliasedColumns.AddRange(leftColumns);
      aliasedColumns.AddRange(rightColumns);
      AliasedColumns = new SqlColumnCollection(aliasedColumns);
    }
  }
}
