// Copyright (c) 2005,2006,2007,2009,2010,2011 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v6.2/Surface_sweep_2/include/CGAL/Surface_sweep_2_algorithms.h $
// $Id: include/CGAL/Surface_sweep_2_algorithms.h cac3e9d75e2 $
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
//             Efi Fogel       <efif@post.tau.ac.il>
//             (based on old version by Tali Zvi)

#ifndef CGAL_SURFACE_SWEEP_2_ALGORITHMS_H
#define CGAL_SURFACE_SWEEP_2_ALGORITHMS_H

#include <CGAL/license/Surface_sweep_2.h>

/*! File
 *
 * \file Definition of the surface-sweep related functions.
 */

#include <CGAL/Surface_sweep_2.h>
#include <CGAL/Do_intersect_surface_sweep_2.h>
#include <CGAL/Surface_sweep_2/Default_arr_traits.h>
#include <CGAL/Surface_sweep_2/Intersection_points_visitor.h>
#include <CGAL/Surface_sweep_2/Subcurves_visitor.h>
#include <CGAL/Surface_sweep_2/Do_intersect_visitor.h>
#include <CGAL/Surface_sweep_2/Surface_sweep_2_utils.h>

namespace CGAL {
namespace Surface_sweep_2 {

/*! Determine whether any curves in a given range intersect pairwise.
 * \param begin An input iterator of the the range.
 * \param end A input past-the-end iterator of the range.
 * \param consider_common_endpoints Indicates whether common endpoints should be considered.
 * \return (true) if any pair of curves intersect; (false) otherwise.
 */
template <typename CurveInputIterator, typename Traits>
bool do_intersect(CurveInputIterator begin, CurveInputIterator end, bool consider_common_endpoints, Traits& traits) {
  // If the curves are not \f$x\f$-monotone, subdivide them into \f$x\f$-monotone curves.
  using Visitor = Do_intersect_visitor<Traits>;
  using Surface_sweep = Do_intersect_surface_sweep_2<Visitor>;

  Visitor visitor;
  Surface_sweep surface_sweep(&traits, &visitor, consider_common_endpoints);

  using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
  using value_type = typename std::iterator_traits<CurveInputIterator>::value_type;
  if constexpr (std::is_same_v<value_type, X_monotone_curve_2>) {
    surface_sweep.do_intersect_sweep(begin, end);
    return visitor.do_intersect();
  }
  else {
    using Point_2 = typename Traits::Point_2;
    std::vector<X_monotone_curve_2> xcurves;
    std::vector<Point_2> points;
    xcurves.reserve(std::distance(begin, end));
    make_x_monotone(begin, end, std::back_inserter(xcurves), std::back_inserter(points), traits);
    surface_sweep.do_intersect_sweep(xcurves.begin(), xcurves.end(), points.begin(), points.end());
    return visitor.do_intersect();
  }
}

/*!
 */
template <typename CurveInputIterator>
bool do_intersect(CurveInputIterator begin, CurveInputIterator end, bool consider_common_endpoints = true) {
  using Curve = typename std::iterator_traits<CurveInputIterator>::value_type;
  typename Default_arr_traits<Curve>::Traits traits;
  return do_intersect(begin, end, consider_common_endpoints, traits);
}

} // namespace Surface_sweep_2

namespace Ss2 = Surface_sweep_2;

/*! Compute all intersection points induced by a range of input curves.
 * The intersections are calculated using the surface-sweep algorithm.
 * \param begin An input iterator for the first curve in the range.
 * \param end A input past-the-end iterator for the range.
 * \param points Output: An output iterator for the intersection points
 *                       induced by the input curves.
 * \param report_endpoints If (true), the end points of the curves are also
 *                         reported as intersection points.
 * \pre The value-type of CurveInputIterator is Traits::Curve_2, and the
 *      value-type of OutputIterator is Traits::Point_2.
 */
template <typename CurveInputIterator, typename OutputIterator, typename Traits>
OutputIterator compute_intersection_points(CurveInputIterator begin, CurveInputIterator end,
                                           OutputIterator points, bool report_endpoints, Traits& traits) {
  // Define the surface-sweep types:
  using Visitor = Ss2::Intersection_points_visitor<Traits, OutputIterator>;
  using Surface_sweep = Ss2::Surface_sweep_2<Visitor>;

  // Perform the sweep and obtain the intersection points.
  Visitor visitor(points, report_endpoints);
  Surface_sweep surface_sweep(&traits, &visitor);

  using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
  using value_type = typename std::iterator_traits<CurveInputIterator>::value_type;
  if constexpr (std::is_same_v<value_type, X_monotone_curve_2>) {
    surface_sweep.sweep(begin, end);
    return visitor.output_iterator();
  }
  else {
    using Point_2 = typename Traits::Point_2;
    std::vector<X_monotone_curve_2> xcurves;
    std::vector<Point_2> points;
    xcurves.reserve(std::distance(begin, end));
    Ss2::make_x_monotone(begin, end, std::back_inserter(xcurves), std::back_inserter(points), traits);
    surface_sweep.sweep(xcurves.begin(), xcurves.end(), points.begin(), points.end());
    return visitor.output_iterator();
  }
}

/*!
 */
template <typename CurveInputIterator, typename OutputIterator>
OutputIterator compute_intersection_points(CurveInputIterator begin, CurveInputIterator end,
                                           OutputIterator points, bool report_endpoints = false) {
  using Curve = typename std::iterator_traits<CurveInputIterator>::value_type;
  typename Ss2::Default_arr_traits<Curve>::Traits traits;
  return compute_intersection_points(begin, end, points, report_endpoints, traits);
}

/*! Compute all x-monotone subcurves that are disjoint in their interiors
 * induced by a range of input curves.
 * The subcurves are calculated using the surface-sweep algorithm.
 * \param begin An input iterator for the first curve in the range.
 * \param end A input past-the-end iterator for the range.
 * \param points Output: An output iterator for the subcurve.
 * \param mult_overlaps If (true), the overlapping subcurve will be reported
 *                      multiple times.
 * \pre The value-type of CurveInputIterator is Traits::Curve_2, and the
 *      value-type of OutputIterator is Traits::X_monotone_curve_2.
 */
template <typename CurveInputIterator, typename OutputIterator, typename Traits>
OutputIterator compute_subcurves(CurveInputIterator begin, CurveInputIterator end,
                                 OutputIterator subcurves, bool mult_overlaps, Traits& traits) {
  // Define the surface-sweep types:
  using Visitor = Ss2::Subcurves_visitor<Traits, OutputIterator>;
  using Surface_sweep = Ss2::Surface_sweep_2<Visitor>;

  // Perform the sweep and obtain the subcurves.
  Visitor visitor(subcurves, mult_overlaps);
  Surface_sweep surface_sweep(&traits, &visitor);

  using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
  using value_type = typename std::iterator_traits<CurveInputIterator>::value_type;
  if constexpr (std::is_same_v<value_type, X_monotone_curve_2>) {
    surface_sweep.sweep(begin, end);
    return visitor.output_iterator();
  }
  else {
    using Point_2 = typename Traits::Point_2;
    std::vector<X_monotone_curve_2> xcurves;
    std::vector<Point_2> points;
    xcurves.reserve(std::distance(begin, end));
    Ss2::make_x_monotone(begin, end, std::back_inserter(xcurves), std::back_inserter(points), traits);
    surface_sweep.sweep(xcurves.begin(), xcurves.end(), points.begin(), points.end());
    return visitor.output_iterator();
  }
}

/*!
 */
template <typename CurveInputIterator, typename OutputIterator>
OutputIterator compute_subcurves(CurveInputIterator begin, CurveInputIterator end,
                                 OutputIterator subcurves, bool mult_overlaps = false) {
  using Curve = typename std::iterator_traits<CurveInputIterator>::value_type;
  typename Ss2::Default_arr_traits<Curve>::Traits traits;
  return compute_subcurves(begin, end, subcurves, mult_overlaps, traits);
}

#ifndef CGAL_NO_DEPRECATED_CODE

/*! Determine whether any curves in a given range intersect pairwise.
 * \deprecated This function is deprecated since the version 6.2 of \cgal. Use the function `CGAL::Surface_sweep_2::do_intersect()` instead.
 * \param begin An input iterator of the the range.
 * \param end A input past-the-end iterator of the range.
 * \return (true) if any pair of curves intersect; (false) otherwise.
 */
template <typename CurveInputIterator, typename Traits>
CGAL_DEPRECATED
bool do_curves_intersect(CurveInputIterator begin, CurveInputIterator end, Traits& traits)
{ return Ss2::do_intersect(begin, end, false, traits); }

/*!
 * \deprecated This function is deprecated since the version 6.2 of \cgal. Use the function `CGAL::Surface_sweep_2::do_intersect()` instead.
 */
template <typename CurveInputIterator>
CGAL_DEPRECATED
bool do_curves_intersect(CurveInputIterator begin, CurveInputIterator end)
{ return Ss2::do_intersect(begin, end, false); }

#endif

} // namespace CGAL

#endif
