#region License Information
/* HeuristicLab
 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
 *
 * This file is part of HeuristicLab.
 *
 * HeuristicLab is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * HeuristicLab is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
 */
#endregion

using System.Collections.Generic;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Optimization;
using HEAL.Attic;

namespace HeuristicLab.Selection {
  /// <summary>
  /// Reduces the sub-scopes, so that the selected sub-scope contains all selected leaves (1) and (2)
  /// and the remaining sub-scope contains the sub-scopes of the bottom-most remaining scope (3).
  /// <pre>                                                      
  ///                  scope            scope  
  ///                   / \             /   \      
  ///                  R   S(1)   =>   R     S                 
  ///                 / \     \       /|\   /|\       
  ///               R(3) S(2)  C     ABCDEF  CDEF      
  ///               /|\  /|\                              
  ///             ABCDEF DEF                             
  /// </pre>
  /// </summary>
  [Item("RightChildReducer", "Merges all sub-scopes generated by successively selecting sub-scopes of the remaining part.")]
  [StorableType("D1857728-A661-46BE-AA08-CDF830DD81A8")]
  public class RightChildReducer : Reducer, IReducer {
    [StorableConstructor]
    protected RightChildReducer(StorableConstructorFlag _) : base(_) { }
    protected RightChildReducer(RightChildReducer original, Cloner cloner) : base(original, cloner) { }
    public override IDeepCloneable Clone(Cloner cloner) {
      return new RightChildReducer(this, cloner);
    }
    public RightChildReducer() : base() { }
    /// <summary>
    ///  Reduces the sub-scopes, so that the selected sub-scope contains all selected leaves
    /// and the remaining sub-scope contains the sub-scopes of the bottom-most remaining scope.
    /// </summary>
    /// <param name="scope">The current scope to reduce.</param>
    /// <returns>A list of the new reduced sub scopes.</returns>
    protected override List<IScope> Reduce(List<IScope> scopes) {
      IScope rightChild = scopes[scopes.Count - 1];
      IScope leftChild = scopes[0];
      while (leftChild.SubScopes.Count > 1 && leftChild.SubScopes[0].SubScopes.Count > 0) {
        IScope leftRightChild = leftChild.SubScopes[leftChild.SubScopes.Count - 1];

        // merge right children
        while (leftRightChild.SubScopes.Count > 0) {
          IScope leftRightChildChild = leftRightChild.SubScopes[0];
          leftRightChild.SubScopes.RemoveAt(0);
          rightChild.SubScopes.Add(leftRightChildChild);
        }

        leftChild = leftChild.SubScopes[0];
      }
      List<IScope> subScopes = new List<IScope>();
      subScopes.Add(leftChild);
      subScopes.Add(rightChild);
      return subScopes;
    }
  }
}