#include "commend.h"
#include "string.h"
#include "mystring.h"
#include "bytearray.h"
//#include "mystdlib.h"
#include "debug.h"
#include "board.h"

#define CMD_RETURN_BUFF_SIZE 1024



typedef struct{
  char *data;
}self_def;



static self_def g_self;
void *tappend(void *p,void *del);



static commend_def *cmd_find(char *name)
{
#if defined (__CC_ARM)  
  extern const int cmdstruct$$Base;
  extern const int cmdstruct$$Limit;
  commend_def *start=(commend_def *)&cmdstruct$$Base;
  commend_def *end=(commend_def *)&cmdstruct$$Limit;
#elif defined(__GNUC__)
  extern const int __start_cmdstruct;
  extern const int __stop_cmdstruct;
  commend_def *start=(commend_def *)&__start_cmdstruct;
  commend_def *end=(commend_def *)&__stop_cmdstruct;
#endif
  for(commend_def *t=start;t<end;t++)
  {
    if(strcmp(t->name,name)==0)
    {
      return t;
    }
  }
  return 0;
}





void cmd_recv_slot(void *obj,const char *coder,uint8_t cmd,array_def *data,char *err_str)
{
  self_def *s=&g_self;
  commend_def *commd;
  if((strcmp(err_str,"ok")!=0)||(cmd!=0)){
    return;
  }
  list_def *argv=str_split(str_simplified((const char *)arr_data(data)),' ');
  DBG_LOG("list_str=%s",str_temp(list_string(argv)));
  commd=cmd_find(list_get_str(argv,0));
  if(commd&&commd->fun) commd->fun(argv);
  else cmd_print("unknown cmd of \"%s\"",list_get_str(argv,0));
}


static int cmd_init(void)
{
  self_def *s=&g_self;
  if(s->data==0){
    s->data=calloc(CMD_RETURN_BUFF_SIZE,sizeof(char));
  }
  app_variable("cmd",s,0);
  return 0;
}
app_init_export(cmd_init);


int cmd_print(const char *fmt,...)
{
  self_def *s=&g_self;
  if(s->data==0) return 0;
  va_list args;
  size_t length=0;
  va_start(args, fmt);
  length += vsnprintf(&s->data[length], CMD_RETURN_BUFF_SIZE - length - 1, fmt, args);
  if (length > CMD_RETURN_BUFF_SIZE - 1)
    length = CMD_RETURN_BUFF_SIZE - 1;
  va_end(args);
  memcpy(&s->data[length],"\r\n",2);
  length+=2;
  s->data[length]=0;
  array_def *arr=arr_creat();
  arr_appends(arr,s->data,length);
  emit cmd_reply_signal(s,0,arr_temp(arr));
  return length;
}

// 这个不会自动加换行
int cmd_printf(const char *fmt,...)
{
  self_def *s=&g_self;
  if(s->data==0) return 0;
  va_list args;
  size_t length=0;
  va_start(args, fmt);
  length += vsnprintf(&s->data[length], CMD_RETURN_BUFF_SIZE - length - 1, fmt, args);
  if (length > CMD_RETURN_BUFF_SIZE - 1)
    length = CMD_RETURN_BUFF_SIZE - 1;
  va_end(args);
  s->data[length]=0;
  array_def *arr=arr_creat();
  arr_appends(arr,s->data,length);
  emit cmd_reply_signal(s,0,arr_temp(arr));
  return length;
}






static int cmd_help(list_def *argv)
{
#if defined (__CC_ARM)  
  extern const int cmdstruct$$Base;
  extern const int cmdstruct$$Limit;
  commend_def *start=(commend_def *)&cmdstruct$$Base;
  commend_def *end=(commend_def *)&cmdstruct$$Limit;
#elif defined (__GNUC__)
  extern const int __start_cmdstruct;
  extern const int __stop_cmdstruct;
  commend_def *start=(commend_def *)&__start_cmdstruct;
  commend_def *end=(commend_def *)&__stop_cmdstruct;
#endif
  cmd_print("help ->");
  for(commend_def *t=start;t<end;t++)
  {
    cmd_print("%-15s: %s",t->name,t->help);
  }
  return 0;
}

commend_export(help,cmd_help,"print the help str of cmds.")

