/**********************************************************************
This file is part of Crack dot Com's free source code release of Golgotha.
for information about compiling & licensing issues visit this URL
 If that doesn't help, contact Jonathan Clark at 
  golgotha_source@usa.net (Subject should have "GOLG" in it) 
***********************************************************************/


#include "editor/mode/e_ai.hh"
#include "editor/e_state.hh"
#include "critical_graph.hh"
#include "map.hh"
#include "map_man.hh"
#include "g1_render.hh"
#include "editor/contedit.hh"
#include "editor/editor.hh"
#include "gui/butbox.hh"

g1_ai_params g1_e_ai;

g1_mode_handler::state g1_ai_mode::current_state()
{
  w8 remap[]={ ROTATE,
               ZOOM,
               DRAG_SELECT,
               DRAG_SELECT,
               OTHER,
               OTHER
  };

  I4_ASSERT(g1_edit_state.ai.minor_mode<=sizeof(remap), "state too big");

  return (g1_mode_handler::state)remap[g1_e_ai.get_minor_mode()];
}


g1_ai_mode::g1_ai_mode(g1_controller_edit_class *c)
  : g1_mode_handler(c)
{
  sel_color=0xffff00;
  norm_color=0x7f7f7f;
}


void g1_ai_mode::post_draw(i4_draw_context_class &context)
{
  g1_map_class *map=g1_get_map();
  if (map)
  {
    g1_critical_graph_class *graph=map->get_critical_graph();
    if (graph)
    {
      for (int i=1; icriticals; i++)
      {
        float x = graph->critical[i].x, y=graph->critical[i].y, z;
        x = (float)((int)x)+0.5;
        y = (float)((int)y)+0.5;

        z=map->terrain_height(x,y)+0.01;
        
        r1_vert rv;
        int w1=2,w2=1;
        if (g1_render.project_point(i4_3d_point_class(x,y,z), 
                                    rv, c->g1_context.transform))
        {          
          w32 color;
          if (graph->critical[i].selected)
            color=sel_color;
          else
            color=norm_color;

          
          r1_clip_clear_area((sw32)rv.px-w1, (sw32)rv.py-w1, 
                             (sw32)rv.px+w1, (sw32)rv.py+w1, 
                             0, 0.02, *c->g1_context.context, g1_render.r_api);

          r1_clip_clear_area((sw32)rv.px-w2, (sw32)rv.py-w2, 
                             (sw32)rv.px+w2, (sw32)rv.py+w2, 
                             color, 0.01, *c->g1_context.context, g1_render.r_api);
        }
      }
    }
  }

  g1_mode_handler::post_draw(context);
}

g1_critical_graph_class *g1_ai_mode::get_graph()
{
  g1_map_class *map=g1_get_map();
  if (map)
    return map->get_critical_graph();  
  return 0;
}

void g1_ai_mode::mouse_down()
{
  if (g1_e_ai.get_minor_mode()==g1_ai_params::CREATE)
  {
    g1_critical_graph_class *graph=get_graph();
    i4_float gx,gy, dx,dy;
    if (!c->view_to_game(lx(), ly(), gx,gy, dx,dy))
      return;

    g1_map_class *map=g1_get_map();
    g1_editor_instance.add_undo(G1_MAP_CRITICAL_POINTS);
    if (map) map->mark_for_recalc(G1_RECALC_CRITICAL_DATA);
    graph->add_critical_point(gx, gy);
  }
  else g1_mode_handler::mouse_down();
}



i4_bool g1_ai_mode::select_object(sw32 mx, sw32 my, 
                                  i4_float &ox, i4_float &oy, i4_float &oz,
                                  select_modifier mod)
{
  i4_bool change=i4_F;

 
  no_more_move_undos=i4_F;

  g1_critical_graph_class *graph=get_graph();
  if (!graph) return i4_F;
  g1_map_class *map=g1_get_map();

  if (mod!=FOR_CURSOR_HINT)
    g1_editor_instance.add_undo(G1_MAP_CRITICAL_POINTS);

  i4_bool ret=i4_F;
  int t=graph->criticals;
  for (int i=1; icritical+i;
    float x=((int)p->x)+0.5, y=((int)p->y)+0.5, z;
    z=map->terrain_height(x,y)+0.01;

    r1_vert rv;
    if (g1_render.project_point(i4_3d_point_class(x,y,z), rv, c->g1_context.transform))
    {
      if (abs((sw32)rv.px-mx)<3 && abs((sw32)rv.py-my)<3)
      {
        ox=x;  oy=y;  oz=z;

        if (p->selected==0 && mod==CLEAR_OLD_IF_NO_SELECTION)
          for (int j=1; jcritical[j].selected=0;

        if (mod==CLEAR_OLD_IF_NO_SELECTION || mod==ADD_TO_OLD)
        {
          p->selected=1;
          change=i4_T;
        }
        else if (mod==SUB_FROM_OLD)
        {
          p->selected=0;
          change=i4_T;
        }

        ret=i4_T;        
      }
    }
  }

  if (change)
  {
    c->changed();
    c->refresh();
  }


  return ret;
}

void g1_ai_mode::select_objects_in_area(sw32 x1, sw32 y1, sw32 x2, sw32 y2, 
                                            select_modifier mod)
{
  no_more_move_undos=i4_F;


  g1_critical_graph_class *graph=get_graph();
  if (!graph) return;
  g1_map_class *map=g1_get_map();

  g1_editor_instance.add_undo(G1_MAP_CRITICAL_POINTS);

  int t=graph->criticals;
  for (int i=1; icritical+i;
    float x=p->x, y=p->y, z;
    z=map->terrain_height(x,y)+0.01;

    r1_vert rv;
    if (g1_render.project_point(i4_3d_point_class(x,y,z), rv, c->g1_context.transform))
    {
      if (rv.px>=x1 && rv.px<=x2 && rv.py>=y1 && rv.py<=y2)
      {
        if (mod==SUB_FROM_OLD)
          p->selected=0;
        else
          p->selected=1;
      }
      else if (mod==CLEAR_OLD_IF_NO_SELECTION)
        p->selected=0;
    }
  }
}

void g1_ai_mode::move_selected(i4_float xc, i4_float yc, i4_float zc, 
                               sw32 mouse_x, sw32 mouse_y)
{
  g1_critical_graph_class *graph=get_graph();
  if (!graph) return;
  g1_map_class *map=g1_get_map();

  g1_editor_instance.add_undo(G1_MAP_CRITICAL_POINTS);
  map->mark_for_recalc(G1_RECALC_CRITICAL_DATA);
  
  int t=graph->criticals;
  for (int i=1; icritical+i;
    if (p->selected)
    {
      p->x+=xc;  if (p->x<0) p->x=0; else if (p->x>=map->width()) p->x=map->width()-0.1;
      p->y+=yc;  if (p->y<0) p->y=0; else if (p->y>=map->height()) p->y=map->height()-0.1;
    }
  } 
}

void g1_ai_mode::delete_selected()
{
  g1_critical_graph_class *graph=get_graph();
  if (!graph) return;
  g1_map_class *map=g1_get_map();

  g1_editor_instance.add_undo(G1_MAP_CRITICAL_POINTS);
  map->mark_for_recalc(G1_RECALC_CRITICAL_DATA);
  
  for (int i=1; icriticals; i++) 
  {
    if (graph->critical[i].selected)
    {
      for (int j=i;jcriticals-1; j++)
        graph->critical[j]=graph->critical[j+1];
      graph->criticals--;
    }
  } 
}




void g1_ai_params::create_buttons(i4_parent_window_class *container)
{
  i4_button_box_class *box=new i4_button_box_class(&g1_edit_state);
  char *rn[]={"aROTATE", "aZOOM", "aMOVE", "aSELECT", "aCREATE", 0 };
  w32 i=ROTATE;


  for (char **a=rn; *a; i++, a++)
    g1_edit_state.add_but(box, *a, 0, (i4_bool) i==get_minor_mode(),
                          new g1_set_minor_mode_event("AI",i));

  box->arrange_right_down();

  i4_button_class *create=g1_edit_state.create_button("aRECALC", RECALC, i4_T);

  i4_graphical_style_class *s=get_style();
  i4_color_window_class *cw=new i4_color_window_class(box->width(), 
                                                      box->height()+create->height(),
                                                      s->color_hint->window.passive.medium,
                                                      s);
  container->add_child(0, 0, box);
  container->add_child(0, box->height(), create);

}




i4_bool g1_ai_params::set_minor_mode(w8 m) 
{ 
  if (m<=CREATE)
    minor_mode=(minor_mode_type)m; 
  if (m==RECALC)
  {
    g1_map_class *map=g1_get_map();
    if (map)
    {
      map->mark_for_recalc(G1_RECALC_BLOCK_MAPS |
                           G1_RECALC_CRITICAL_DATA);
      map->recalc_static_stuff();
    }
  }
  return i4_T;
}