#include <LEDA/window.h>
#include <LEDA/plane_alg.h>
#include <LEDA/graphwin.h>

static GRAPH<rat_point,rat_segment>* gp;

void report_intersection(const rat_segment& s1, const rat_segment& s2)
{ rat_point p;
  s1.intersection_of_lines(s2,p);
  gp->new_node(p);
 }


void run_alg(window& W, string alg, const list<rat_segment>& seglist, 
                        GRAPH<rat_point,rat_segment>& G)
{
    W.clear();
    int j = 0;
    rat_segment s;
    forall(s,seglist) 
    { color c = color(1 + (j++ % 15));
      W.draw_segment(s.to_segment(),c);
     }

    G.clear();

    W.message(alg);

    float T = used_time();
  
    if (alg == "sweep")    
      SWEEP_SEGMENTS(seglist,G);
  
    if (alg == "sweep2")   
      SWEEP_SEGMENTS(seglist,G,true);

    if (alg == "mulmuley") 
      MULMULEY_SEGMENTS(seglist,G);

    if (alg == "balaban")
    { BALABAN_SEGMENTS(seglist,report_intersection);
      rat_segment s;
      forall(s,seglist)
      { G.new_node(s.source());
        G.new_node(s.target());
        }
     }

    if (alg == "trivial")
    { TRIVIAL_SEGMENTS(seglist,report_intersection);
      rat_segment s;
      forall(s,seglist)
      { G.new_node(s.source());
        G.new_node(s.target());
       }
     }

    float t = used_time(T);
    int n = G.number_of_nodes();
    int m = G.number_of_edges();

    W.del_messages();
    W.message(string("%s |V| = %d |E| = %d  t = %6.2f sec", alg,n,m,t));
  
    node v;
    forall_nodes(v,G) 
       W.draw_filled_node(G[v].to_point(),red);
}
  




int main()
{ 
  int N = 200;
  int gridlen = 5;
  string alg = "sweep";

  int h = int(0.8 * window::screen_height());
  if (h < 480) h = 480;
  int w = int(0.8 * h);

  window W(w,h);

  list<string> alg_names;
  alg_names.append("sweep");
  alg_names.append("sweep2");
  alg_names.append("mulmuley");
  alg_names.append("balaban");
  alg_names.append("trivial");

  W.int_item("segments", N,0,1000);
  W.int_item("grid size",gridlen,1,40);
  W.string_item("algorithm",alg,alg_names);

  W.button("mouse", 1);
  W.button("random",2);
  W.button("run",   3);
  W.button("graph", 4);
  W.button("quit",  0);

  W.set_node_width(2);
  W.init(-1000,1000,-1000);
  W.display();

  list<rat_segment> seglist;
  GRAPH<rat_point,rat_segment> G;

  for(;;)
  {
    gp = &G;

    int but = W.read_mouse();

    if (but == 0) break;
  
    switch (but) {

       case 1: // mouse
         { seglist.clear();

           int grid_width = int((W.xmax() - W.xmin())/(gridlen+1));
           W.set_grid_mode(grid_width);
     
           segment s;
           while (W >> s)
           { W << s;
             int x1 = int(s.xcoord1());
             int y1 = int(s.ycoord1());
             int x2 = int(s.xcoord2());
             int y2 = int(s.ycoord2());
             seglist.append(rat_segment(x1,y1,1,x2,y2,1));
            }
     
           break;
          }
     
   
       case 2: // random
        { seglist.clear();

          W.set_grid_mode(0);

          int xmin = int(W.xmin())+100;
          int xmax = int(W.xmax())-100;
          int ymin = int(W.ymin())+100;
          int ymax = int(W.ymax())-100;

          int dx = (xmax - xmin)/gridlen;
          int dy = (ymax - ymin)/gridlen;

          for(int i = 0; i < N; i++)
          { int x1 = xmin + rand_int(0,gridlen)*dx;
            int y1 = ymin + rand_int(0,gridlen)*dy;
            int x2 = xmin + rand_int(0,gridlen)*dx;
            int y2 = ymin + rand_int(0,gridlen)*dy;
            seglist.append(rat_segment(x1,y1,1,x2,y2,1));
            W.del_messages();
            W.message(string("%4d",i));
           }
           break;
        }

    case 3: { // run algorithm
              run_alg(W,alg,seglist,G);
              break;
             }

    case 4: { // start GraphWin
              char* buf = W.get_window_pixrect();
              GraphWin gw(G,W);
              gw.set_node_label_type(no_label);
              gw.set_directed(true);
              node v;
              forall_nodes(v,G) 
              { point p = G[v].to_point();
                gw.set_position(v,p);
                gw.set_width(v,8);
               }
              gw.display();
              gw.wait();
              W.put_pixrect(buf);
              W.del_pixrect(buf);
              break;
             }

    }

    if (but == 1 || but == 2)
    { G.clear();
      W.clear();
      int j = 0;
      rat_segment s;
      forall(s,seglist) 
      { color c = color(1 + (j++ % 15));
        W.draw_segment(s.to_segment(),c);
      }
    }

}


 rat_point::print_statistics();

 return 0;

}

