// -*- C++ -*-

// Copyright (C) 2005-2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library 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, or (at your option) any later
// version.

// This library 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.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.

// Permission to use, copy, modify, sell, and distribute this software
// is hereby granted without fee, provided that the above copyright
// notice appears in all copies, and that both that copyright notice
// and this permission notice appear in supporting documentation. None
// of the above authors, nor IBM Haifa Research Laboratories, make any
// representation about the suitability of this software for any
// purpose. It is provided "as is" without express or implied
// warranty.

/**
 * @file trie_policy/order_statistics_imp.hpp
 * Contains forward declarations for order_statistics_key
 */

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::iterator
PB_DS_CLASS_C_DEC::
find_by_order(size_type order)
{
  if (empty())
    return end();

  ++order;
  node_iterator nd_it = node_begin();

  while (true)
    {
      if (order > nd_it.get_metadata())
	return ++base_type::rightmost_it(nd_it);

      const size_type num_children = nd_it.num_children();
      if (num_children == 0)
	return *nd_it;

      for (size_type i = 0; i < num_children; ++i)
	{
	  node_iterator child_nd_it = nd_it.get_child(i);
	  if (order <= child_nd_it.get_metadata())
	    {
	      i = num_children;
	      nd_it = child_nd_it;
	    }
	  else
	    order -= child_nd_it.get_metadata();
	}
    }
}

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::const_iterator
PB_DS_CLASS_C_DEC::
find_by_order(size_type order) const
{ return const_cast<PB_DS_CLASS_C_DEC*>(this)->find_by_order(order); }

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::size_type
PB_DS_CLASS_C_DEC::
order_of_key(key_const_reference r_key) const
{
  const _ATraits& r_traits =
    const_cast<PB_DS_CLASS_C_DEC* >(this)->get_access_traits();

  return order_of_prefix(r_traits.begin(r_key), r_traits.end(r_key));
}

PB_DS_CLASS_T_DEC
inline typename PB_DS_CLASS_C_DEC::size_type
PB_DS_CLASS_C_DEC::
order_of_prefix(typename access_traits::const_iterator b,
		typename access_traits::const_iterator e) const
{
  if (empty())
    return 0;

  const _ATraits& r_traits =
    const_cast<PB_DS_CLASS_C_DEC*>(this)->get_access_traits();

  node_const_iterator nd_it = node_begin();
  node_const_iterator end_nd_it = node_end();
  size_type ord = 0;

  while (true)
    {
      const size_type num_children = nd_it.num_children();
      if (num_children == 0)
	{
	  key_const_reference r_key = base_type::extract_key(*(*nd_it));
	  typename access_traits::const_iterator key_b =
	    r_traits.begin(r_key);

	  typename access_traits::const_iterator key_e =
	    r_traits.end(r_key);

	  return (base_type::less(key_b, key_e,  b, e,  r_traits)) ?
		  ord + 1 : ord;
	}

      node_const_iterator next_nd_it = end_nd_it;
      size_type i = num_children - 1;

      do
	{
	  node_const_iterator child_nd_it = nd_it.get_child(i);

	  if (next_nd_it != end_nd_it)
	    ord += child_nd_it.get_metadata();
	  else if (!base_type::less(b, e,
				    child_nd_it.valid_prefix().first,
				    child_nd_it.valid_prefix().second,
				    r_traits))
	    next_nd_it = child_nd_it;
	}
      while (i-- > 0);

      if (next_nd_it == end_nd_it)
	return ord;

      nd_it = next_nd_it;
    }
}

PB_DS_CLASS_T_DEC
inline void
PB_DS_CLASS_C_DEC::
operator()(node_iterator nd_it, node_const_iterator /*end_nd_it*/) const
{
  const size_type num_children = nd_it.num_children();
  size_type children_rank = 0;
  for (size_type i = 0; i < num_children; ++i)
    children_rank += nd_it.get_child(i).get_metadata();

  const size_type res = (num_children == 0) ? 1 : children_rank;
  const_cast<size_type&>(nd_it.get_metadata()) = res;
}
