
#include <CGAL/basic.h>
#include<CGAL/Handle_for.h>
#include <CGAL/Cartesian.h>
#include <CGAL/point_generators_2.h>

#include <CGAL/MP_Float.h>

#include <CGAL/Algebraic_kernel_for_circles_2_2.h>

#include <CGAL/intersections.h>

#include <CGAL/Circular_kernel_2.h>
#include <CGAL/Circular_arc_traits.h>
#include <CGAL/Circular_arc_traits_tracer.h>

#include <CGAL/Filtered_bbox_circular_kernel_2.h>

#include <CGAL/Arrangement_2.h>
#include <CGAL/Arr_naive_point_location.h>
#include <CGAL/Variant_traits.h>


#include "IntStr.h"
#include "benchmark_parser.h"
#include <iostream>
#include <sstream>
template <typename K,class ArcContainer>
struct Breader : public Benchmark_visitor {
        typedef typename CGAL::Quotient<CGAL::MP_Float>                       NT1;
        typedef typename K::Point_2 Point_2;
          typedef typename K::Circle_2 Circle_2;
          typedef std::list<Circle_2> Circles;
        typedef std::list<Point_2> Points;
        typedef std::list<NT1> Numbers;
          typedef std::list<std::pair<Point_2, double> > Polygon;
          typedef std::list<Polygon> Polygons;
        Points points;
        Numbers numbers;
        Circles circles;
        Polygons polygons;
        int x_;
        int y_;
    Breader() {}
    virtual void token_not_handled( std::string s) {}
    virtual void accept_benchmark_name( std::string s) {
        Benchmark_visitor::accept_benchmark_name(s);
        std::cerr << "name '" << s << "', ";
    }

    virtual void accept_classification( std::string problem,
                                        std::string geom,
                                        std::string clas,
                                        std::string family,
                                        std::string instance,
                                        std::string release) {

        if ((problem != "Arrangement") && (problem != "CSG")
            && (problem != " "))
            error_handler
                ( "classification error");

        if ((geom != "Lines") && (geom != "Circles") && (geom != "Conics")
            && (geom != "Cubics") && (geom != "Quartics")
            && (geom != "ArbitraryDegreeCurves") && ( geom != "Quadrics")
            && (geom != "Tori") && (geom != "Planes") && (geom != " "))
            error_handler ( "classification error" );

        if ((clas != "FullCurves") && (clas != "Ellipses")
            && (clas != "BoundedArcs") && (clas != "UnboundedArcs")
            && (clas != "FullSurfaces") && (clas != "BoundedPatches")
            && (clas != "UnboundedPatches") && (clas != " "))
            error_handler ( "classification error" );
    }
        virtual void begin_circle_2() {

                std::cerr << "circle begin" << std::endl;
                x_=0;
                y_=0;
        }

        virtual void end_circle_2() {

                std::cerr << "circle end" << std::endl;
                //Circle_2 cyrc = typename K::Construct_circle_2()(Point_2(x_,y_), integer*integer);
                NT1 r= numbers.back();
                Circle_2 circ = typename K::Construct_circle_2()(points.back(), r*r);
                circles.push_back(circ);
        }

        virtual void accept_point_2( std::string x, std::string y) {

                std::cerr << "accept_point_2 :"<<x << " ; "<< y << std::endl;

                NT1 qx,qy;
                from_string(qx,x);
                from_string(qy,y);
                points.push_back(typename K::Construct_point_2()(qx,qy));
                std::cerr << "accept_point_2 :"<<qx << " ; "<< qy << std::endl;
        }
        virtual void accept_rational( std::string num, std::string denom) {


                CGAL::MP_Float _num,_denom;
                from_string(_num,num);
                from_string(_denom,denom);
                NT1 x(_num,_denom);
                std::cerr << "accept rat:"<<x<< std::endl;
                numbers.push_back(x);
        }

        virtual void accept_point_2( std::string x_num, std::string x_denom,
                                 std::string y_num, std::string y_denom) {


                CGAL::MP_Float num,denom;
                from_string(num,x_num);
                from_string(denom,x_denom);
                NT1 x(num,denom);
                from_string(num,y_num);
                from_string(denom,y_denom);
                NT1 y(num,denom);
                std::cerr << "accept_point_2(rational) :"<< x<<","<< y<< std::endl;
                tnh( "Point_2(x_num, x_denom, y_num, y_denom)");
                points.push_back(typename K::Construct_point_2()(x,y));
            }
        virtual void accept_integer( std::string s) {

                NT1 n;
                from_string(n,s);
                std::cerr <<"accept_integer!!!!"<<n <<std::endl;
                numbers.push_back(n);

        }
        virtual void begin_line_segment_2() {
                std::cerr <<"Begin_line_segment_2"<<std::endl; }

        virtual void end_line_segment_2() {
                std::cerr <<"end_line_segment_2"<<std::endl;
                Polygon p1;
                Polygon p2;
                typename Points::iterator pit = points.end();
                p2.push_back(std::make_pair(*pit, 0));
                pit--;
                p1.push_back(std::make_pair(*pit, 0));
                polygons.push_back(p1);
                polygons.push_back(p2);
        }
            virtual void begin_CircularArc_2(){
                std::cerr <<"begin_Circular_arc_2"<<std::endl;
        }

            virtual void end_CircularArc_2(){
                std::cerr <<"end_Circular_arc_2"<<std::endl;
        }
   virtual void begin_LineArc_2(){
        tnh("begin_line_arc_2");
        std::cerr <<"begin_line_arc_2"<<std::endl;
        }

    virtual void end_LineArc_2(){
        tnh("end_line_arc_2");
        std::cerr <<"end_line_arc_2"<<std::endl;
        }
   virtual void begin_CircularPoint_2(){
        tnh("begin_circular_arc_poin");
        std::cerr <<"begin_circular_arc_poin"<<std::endl;
        }

    virtual void end_CircularPoint_2(){
        tnh("end_circular_arc_poin");
        std::cerr <<"end_circular_arc_poin"<<std::endl;
        }

};
////
int str_to_int(const char* ch){
int i;
sscanf(ch,"%i",&i);
return i;
}

int main( int argc, char* argv[] ) {

  typedef CGAL::Quotient<CGAL::MP_Float>                       NT1;
  typedef CGAL::Cartesian<NT1>                                 Linear_k1;
  typedef CGAL::Algebraic_kernel_for_circles_2_2<NT1>                      Algebraic_k1;
  typedef CGAL::Circular_kernel_2<Linear_k1, Algebraic_k1>         CK;
  typedef CK::Circular_arc_2                                  Circular_arc_2;
  typedef CK::Line_arc_2                                      Line_arc_2;
  typedef CGAL::Variant_traits<CK,Line_arc_2,Circular_arc_2>  CircularK_Variant_Traits;
  typedef std::variant< Circular_arc_2, Line_arc_2 >        CircularKVarArc;
  typedef std::vector<CircularKVarArc>                        CircularKVarArcContainer;
        CircularKVarArcContainer arc;
        typedef CGAL::Arrangement_2<CircularK_Variant_Traits>                 Pmwx;
          typedef CGAL::Arr_naive_point_location<Pmwx>        Point_location;
        Pmwx _pm;
          Point_location _pl(_pm);
        typedef CK::Circle_2 Circle_2;
        typedef std::list<Circle_2> Circles;

int exit_status = 0;
    if ( argc < 2) {
        return 0;
    } else {
        for ( int i = 1; i < argc; ++i) {
           Breader<CK,CircularKVarArcContainer> check;
            std::cerr << "File '" << argv[i] << "', "<<std::endl;
            if ( benchmark_parse_file( argv[i], &check)) {
                std::cerr<<check.circles.size()<<std::endl;
                std::cerr<<check.polygons.size()<<std::endl;
            } else {
                std::cerr << "is malformed." << std::endl;
                exit_status = 1;

            }
        }
    }


    return exit_status;

}
