#include "qcli.hpp"
#include "QCoreApplication"

bool QCLIDeviceCommands::cli_process_dummy(CLI_shell* shell, const cli::CmdItem<CLICommandBase>& cmd){
    (void)shell;

    if (cmd.dummy == nullptr)
        return false;

    const cli::QCmdItem<CLICommandBase>* qcmd = (const cli::QCmdItem<CLICommandBase>*)&cmd;

    emit_event( qcmd->dummy->copy() );
    return true;
}

void QCLIDeviceCommands::emit_event(QEvent&& x){
    QCoreApplication::postEvent(dummy_target, &x );
}

void QCLIDeviceCommands::emit_event(QObject* target, QEvent&& x){
    QCoreApplication::postEvent(target, &x );
}

// registers sub_cmds events, if they are not registered
void QCLIDeviceCommands::register_dummy_events(){
    cli::QCmdItem<CLICommandBase>* qcmd = (cli::QCmdItem<CLICommandBase>*)sub_cmds;
    for (; qcmd->name != nullptr; ++qcmd){
        cli::QEvent* ev = (cli::QEvent*)qcmd->dummy;
        if (ev != nullptr)
            if (ev->type() == QEvent::None)
                ev->register_me();
    }
}





// takes 1st word from s to w, and return position after word
// @arg s - source string
// @return  NULL - cant parse value
//          w -   updates to new position after word
const char*     cli::pass_word(QString* w, const char* s){
    s += space_len(s);
    if (is_eol(s) >= 0)
        return nullptr;
    int name_size = name_len(s, ~0u);
    if (name_size <= 0)
        return nullptr;
    if (w)
        *w = w->fromLocal8Bit(s, name_size);
    return s+name_size;
}

const QChar*    cli::pass_word(QString* w, const QChar* s){
    s += space_len(s);
    if (is_eol(s) >= 0)
        return nullptr;
    int name_size = name_len(s, ~0u);
    if (name_size <= 0)
        return nullptr;
    if(w)
        *w = w->fromRawData(s, name_size);
    return s+name_size;
}



int cli::space_len(const QChar* s){
    if (s == nullptr)
        return 0;
  const QChar* tmp = s;
  for(; !tmp->isNull() ; tmp++){
    QChar c = *tmp;
    if (!c.isSpace())
      break;
  }
  return tmp - s;
}

int cli::space_len(const QChar* s, unsigned len){
    if (s == nullptr)
        return 0;
  const QChar* tmp = s;
  for(; len > 0; len--, tmp++){
    QChar c = *tmp;
    if (c.isNull())
      break;
    if (!c.isSpace())
      break;
  }
  return tmp - s;
}

int cli::word_len(const QChar* s, unsigned len){
    if (s == nullptr)
        return 0;
  const QChar* tmp = s;
  for(; len > 0; len--, tmp++){
    QChar c = *tmp;
    if (c.isNull())
      break;
    if ( c.isLetterOrNumber()|| c.isPunct() )
      continue;
    break;
  }
  return tmp - s;
}

//* word_len + check that after word is space or EOL
int cli::name_len(const QChar* s, unsigned len){
    if (s == nullptr)
        return 0;
  int res = word_len(s, len);
  if (res >= (int)len)
    return res;
  if (is_eol(s+res) >= 0)
    return res;
  if (s[res].isSpace())
    return res;
  return -1;
}

//* look to EOL or Z
int cli::line_len(const QChar* s, unsigned len){
    if (s == nullptr)
        return 0;
  const QChar* tmp = s;
  for(; len > 0; len--, tmp++){
    int el = is_eol(tmp);
    if (el < 0)
      continue;
    tmp += el;
    break;
  }
  return tmp - s;
}

//* \return < 0 - no eol
//* \returm = 0 - Z ended
//* \return >0  - len of EOL token
int cli::is_eol(const QChar* s){
    if(s == nullptr)
        return 0;
  QChar c = s[0];
  if (c == '\0')
    return 0;
  if (c == '\n')
    return 1;
  return -1;
}

void cli::print(CLI_shell* shell, QStringList x){
    for (auto it = x.cbegin(); it != x.cend(); ++it){
        shell->putln(it->toStdString().c_str());
    }
}


