/**********************************************************************
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_object.hh"
#include "editor/dialogs/obj_win.hh"
#include "gui/scroll_bar.hh"
#include "menu/textitem.hh"
#include "app/app.hh"
#include "gui/deco_win.hh"
#include "g1_render.hh"
#include "r1_win.hh"
#include "device/device.hh"
#include "device/event.hh"
#include "device/keys.hh"
#include "lisp/li_init.hh"
#include "editor/editor.hh"
#include "editor/e_res.hh"

static int to_upper(int ch) { return ch>='a' && ch<='z' ? ch-'a' : ch; }

int obj_name_compare(const g1_object_type *a, const g1_object_type *b)
{
  return strcmp(g1_object_type_array[*a]->name(), g1_object_type_array[*b]->name());
}

class g1_object_picker_class : public i4_color_window_class
{
  g1_3d_object_window *obj_view;

  i4_array selectable;
  i4_array text;
  int offset;
  w32 bg_color;


public:
  enum { W=128,H=400 };

  void recolor_text()
  {
    for (int i=0; i=selectable.size() ||
          selectable[i+offset]==g1_e_object.get_object_type())
        new_color=0xffff00;
      else
        new_color=bg_color;

      if (text[i]->bg_color!=new_color)
      {
        text[i]->bg_color=new_color;
        text[i]->request_redraw(i4_F);
      }        
    }
  }

  void reorient_text()
  {
    for (int i=0; ichange_text(g1_object_type_array[selectable[i+offset]]->name());
      else
        text[i]->change_text("");

    }

    recolor_text();
  }

  void refresh()
  {
    obj_view->set_object_type(g1_e_object.get_object_type(), 0);

    if (obj_view->object.valid())
      obj_view->camera.view_dist=obj_view->object->occupancy_radius()*1.25;

    request_redraw(i4_T);
  }


  g1_object_picker_class()
    : i4_color_window_class(W, H, i4_current_app->get_style()->color_hint->neutral(),
                            i4_current_app->get_style()),
      selectable(0,32),
      text(0,32)
  {

    offset=0;

    g1_3d_pick_window::camera_struct camera;
    camera.init();

    i4_graphical_style_class *style=i4_current_app->get_style();


    w32 l,t,r,b, ow, oh;
    style->get_in_deco_size(l,t,r,b);

    // put the render window in a deco window to make it stand out and look nice
    ow=W-(l+r)-2;
    oh=W-(t+b);

    i4_deco_window_class *deco=new i4_deco_window_class(ow, oh, i4_T, style);
    

    // object view must reside in a render window
    r1_render_window_class *rwin;
    rwin=g1_render.r_api->create_render_window(ow, oh, R1_COPY_1x1);

    obj_view=new g1_3d_object_window(ow, oh,
                                     g1_e_object.get_object_type(),
                                     0,
                                     camera,
                                     0,0, 0);
    
    rwin->add_child(0,0, obj_view);
    deco->add_child(deco->get_x1(), deco->get_y1(), rwin);   
    add_child(l,t, deco);



    // find out which objects are visible to the editor user
    int i=0, y;
    for (i=0; i<=g1_last_object_type; i++)
      if (g1_object_type_array[i] && 
          g1_object_type_array[i]->flags & g1_object_definition_class::EDITOR_SELECTABLE)
        selectable.add(i);

    selectable.sort(obj_name_compare);


    bg_color=style->color_hint->neutral();

    // create text fields so we know how many items fit on the screen
    for (t=0, y=deco->height()+2; yname(),
                                      style, style->color_hint, style->font_hint->small_font,
                                      new i4_event_reaction_class(this, t+1)));

      if (selectable[t]==g1_e_object.get_object_type())
        text[t]->bg_color=0xffff00;
      else
        text[t]->bg_color=bg_color;

        

      add_child(0,y, text[t]);
      y+=text[t]->height();
      t++;
    }
      

    // now add a scroll bar
    i4_scroll_bar *sb=new i4_scroll_bar(i4_T, height()-deco->height(), 
                                        t, selectable.size(), 0, this, style);

    add_child(width()-sb->width(), deco->height()+2, sb);

    // new resize the text fields to fit with the scroll bar
    for (i=0; iresize(W-sb->width(), text[i]->height());
  }


  void select_type(int type)
  {
    g1_edit_state.hide_focus();

    g1_e_object.set_object_type(type);

    if (strcmp(g1_edit_state.major_mode, "OBJECT"))
      g1_edit_state.set_major_mode("OBJECT");

    if (g1_e_object.get_minor_mode() != g1_object_params::ADD)
      g1_edit_state.set_minor_mode("OBJECT", g1_object_params::ADD);

    recolor_text();

    g1_edit_state.show_focus();
  }

  void receive_event(i4_event *ev)
  {
    if (ev->type()==i4_event::USER_MESSAGE)
    {
      CAST_PTR(uev, i4_user_message_event_class, ev);
      
      if (uev->sub_type==0)  // SCROLLBAR message
      {      
        CAST_PTR(sbm, i4_scroll_message, ev);
        offset=sbm->amount;
        reorient_text();
      }
      else                  // selected one of the text fields
        select_type(selectable[uev->sub_type-1+offset]);
    }
    else if (ev->type()==i4_event::KEY_PRESS)
    {
      CAST_PTR(kev, i4_key_press_event_class, ev);
      if (kev->key_code==I4_UP)
      {
        if (offset) { offset--; reorient_text(); }       
      }
      else if (kev->key_code==I4_DOWN)
      {
        if (offsetname())==kev->key_code)
        {
          offset=i;
          select_type(selectable[i]);
          return ;
        }
    }
    else 
      i4_color_window_class::receive_event(ev);
  }

};


i4_event_handler_reference_class g1_object_picker_mp;
i4_event_handler_reference_class g1_object_picker;

void g1_refresh_object_picker()
{
  if (g1_object_picker.get())
    g1_object_picker->refresh();
}


li_object *g1_toggle_object_picker(li_object *o, li_environment *env)
{
  i4_graphical_style_class *style=i4_current_app->get_style();
  if (g1_object_picker.get())
    style->close_mp_window(g1_object_picker.get());
  else
  {
    g1_object_picker=new g1_object_picker_class;
    g1_object_picker_mp=style->create_mp_window(-1,-1, 
                                                g1_object_picker->width(),
                                                g1_object_picker->height(),
                                                g1_ges("object_pick_title"));

    g1_object_picker_mp->add_child(0,0,g1_object_picker.get());
  }

  return 0;
}

li_automatic_add_function(g1_toggle_object_picker, "toggle_object_picker");