#include <stdio.h>
#include <string.h>


#include <libraries/mui.h>
#include <clib/muimaster_protos.h>
#include <clib/utility_protos.h>

#include "mui_tilist.h"

// Custom class MUI

#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

extern struct UtilityBase *UtilityBase;

ULONG MUITIList_Get(struct IClass *cl,Object *obj,Msg msg);
ULONG MUITIList_Set(struct IClass *cl,Object *obj,Msg msg);
ULONG MUITIList_ListVars(struct IClass *cl,Object *obj,Msg msg);
ULONG MUITIList_ListFolders(struct IClass *cl,Object *obj,Msg msg);
ULONG MUITIList_DoubleClick(struct IClass *cl,Object *obj,Msg msg);
ULONG MUITIList_Update(struct IClass *cl,Object *obj,Msg msg);

ULONG MUITIList_Set(struct IClass *cl,Object *obj,Msg msg)
{
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);
  struct TagItem *tags,*tag;

  for (tags=((struct opSet *)msg)->ops_AttrList;(tag=NextTagItem(&tags));)
  {
    switch (tag->ti_Tag)
    {
      case MUIA_TIList_CurrentFolder:
        strncpy(data->current_folder,(char *)(tag->ti_Data),MAX_NAMELENGTH);
        data->current_folder[MAX_NAMELENGTH] = '\0';
        printf("Set ( %s )\n",(char *)tag->ti_Data);
        //DoMethod(obj,MUIM_TIList_ListVars);
        break;

      case MUIA_TIList_ParentApp:
        data->app =  (Object *)(tag->ti_Data);
        break;

      case MUIA_TIList_ParentWindow:
        data->window =  (Object *)(tag->ti_Data);
        break;
    }
  }
  return(DoSuperMethodA(cl,obj,msg));
}

ULONG MUITIList_Get(struct IClass *cl,Object *obj,Msg msg)
{
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);
  ULONG *store = ((struct opGet *)msg)->opg_Storage;

  switch (((struct opGet *)msg)->opg_AttrID)
  {
    case MUIA_TIList_CurrentFolder:
      *store = (ULONG)(&data->current_folder); /* Give a null string */
      return(TRUE);
    case MUIA_TIList_CurrentSelectedVar:
    {
      if ( data->current_folder[0] == '\0' )
        *store = (ULONG)data->current_folder; /* give a null string */
      else
        DoMethod(obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,store);
      return(TRUE);
    }
    case MUIA_TIList_CurrentSelectedFolder:
    {
      if ( data->current_folder[0] != '\0' )
        *store = (ULONG)data->current_folder; /* give a null string */
      else
        DoMethod(obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,store);
      return(TRUE);
    }

    case MUIA_TIList_ParentApp:
      *store = (ULONG)data->app;
      return(TRUE);

    case MUIA_TIList_ParentWindow:
      *store = (ULONG)data->window;
      return(TRUE);
  }

  return(DoSuperMethodA(cl,obj,msg));
}

ULONG MUITIList_ListFolders(struct IClass *cl,Object *obj,Msg msg)
{
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);

  int nbvars, cpt;

  printf("Listing folders...");
  fflush(stdout);
  data->current_folder[0]=0;

  nbvars = ti_folderlist(data->vars);

  if ( nbvars < 0 )
  {
    MUI_Request(data->app,data->window,0,"Error while listing","*_OK",
                ti_code2string(nbvars));
    printf("error %d\n",nbvars);
    return(TRUE);
  }

  DoMethod(obj,MUIM_List_Clear);

  for ( cpt=0; cpt<nbvars; cpt++ )
    DoMethod(obj,MUIM_List_InsertSingle,data->vars[cpt].name,MUIV_List_Insert_Bottom);

  /*SetAttrs((APTR)text_ti89,MUIA_Text_Contents,(ULONG)"TI89 : list of folders",TAG_DONE);*/
  printf("OK\n");
  return(TRUE);
}


ULONG MUITIList_ListVars(struct IClass *cl,Object *obj,Msg msg)
{
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);

  if ( data->current_folder[0] )
  {
    int nbvars, cpt;

    printf("Listing folder %s...",data->current_folder);
    fflush(stdout);

    nbvars = ti_listdir(data->current_folder,data->vars);

    if ( nbvars < 0 )
    {
      MUI_Request(data->app,data->window,0,"Error while listing","*_OK",
                ti_code2string(nbvars));
      return(TRUE);
    }

    DoMethod(obj,MUIM_List_Clear);

    DoMethod(obj,MUIM_List_InsertSingle,"..",MUIV_List_Insert_Bottom);

    for ( cpt=0; cpt<nbvars; cpt++ )
      DoMethod(obj,MUIM_List_InsertSingle,data->vars[cpt].name,MUIV_List_Insert_Bottom);

    printf("OK\n");
  }
  return(TRUE);
}

ULONG MUITIList_DoubleClick(struct IClass *cl,Object *obj,Msg msg)
{
  char *whatisclicked;
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);

  DoMethod(obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&whatisclicked);

  //printf("Double click sur <%s>(%p), cf = <%s>\n",whatisclicked,whatisclicked,data->current_folder);

  if ( ! whatisclicked )
    return(TRUE);

  if ( data->current_folder[0] == '\0' )
  {
    strncpy(data->current_folder,whatisclicked,MAX_NAMELENGTH);

    /*
    sprintf(text_buffer,"TI89 : %s",data->current_folder);
    SetAttrs((APTR)text_ti89,MUIA_Text_Contents,(ULONG)text_buffer,TAG_DONE);
    DoMethod(App,MUIM_Application_ReturnID,LISTVARS_UPDATE);
    */
    DoMethod(obj,MUIM_TIList_ListVars);
  }
  else
    if ( whatisclicked[0] == '.' )
      DoMethod(obj,MUIM_TIList_ListFolders);

  return(TRUE);
}

ULONG MUITIList_Update(struct IClass *cl,Object *obj,Msg msg)
{
  struct MUITIList_Data *data = (struct MUITIList_Data *)INST_DATA(cl,obj);

  if ( data->current_folder[0] )
    DoMethod(obj,MUIM_TIList_ListVars);
  else
    DoMethod(obj,MUIM_TIList_ListFolders);

  return(TRUE);
}

ULONG __attribute__((regparm(3))) MUITIList_Dispatcher(struct IClass *cl ,  Msg msg,Object *obj  )
{
//  printf("Dispatcher ( %x )\n",msg->MethodID);
  switch (msg->MethodID)
  {
    case OM_NEW :
      {
        Object *obj2=(Object *)DoSuperMethodA(cl,obj,(Msg)msg);
        if ( obj2 )
        {
          //printf("OM_NEW...\n");
          DoMethod(obj2, MUIM_Notify, MUIA_Listview_DoubleClick, TRUE,
               MUIV_Notify_Self, 1, MUIM_TIList_DoubleClick);
          return((ULONG)obj2);
        }
      }
      break;

    case OM_SET :
      return(MUITIList_Set(cl,obj,msg));
    case OM_GET :
      return(MUITIList_Get(cl,obj,msg));
    case MUIM_TIList_DoubleClick:
      return(MUITIList_DoubleClick(cl,obj,msg));
    case MUIM_TIList_ListVars :
      return(MUITIList_ListVars(cl,obj,msg));
    case MUIM_TIList_ListFolders :
      return(MUITIList_ListFolders(cl,obj,msg));
    case MUIM_TIList_Update :
      return(MUITIList_Update(cl,obj,msg));
  }

  return(DoSuperMethodA(cl,obj,(Msg)msg));
}


