/*!
  \example ScipUtils.cpp

  \brief SCIP 2.0 応答の受信

  \author Satofumi KAMIMURA

  $Id: ScipUtils.cpp 1000 2009-06-13 22:22:06Z satofumi $
*/

#include "ScipUtils.h"
#include "Connection.h"
#include "ConnectionUtils.h"
#include <cstdlib>

using namespace qrk;
using namespace std;


int decode(const char code[], int byte) {

  int value = 0;
  int i;

  for (i = 0; i < byte; ++i) {
    value <<= 6;
    value &= ~0x3f;
    value |= code[i] - 0x30;
  }
  return value;
}


static char addSum(const char* buf, size_t count) {

  char sum = 0;
  for (size_t i = 0; i < count; ++i) {
    sum += buf[i];
  }
  return sum;
}


int recvReply(Connection* con, int timeout,
              vector<string>* lines) {

  // エコーバックの読み出し
  enum { LineMax = 64 + 1};
  char buffer[LineMax];
  int n = readline(con, buffer, LineMax, timeout);
  if (n <= 0) {
    // !!! 意味が分かる enum に置き換える。enum はヘッダで宣言する
    return ReceiveTimeout;
  }

  // 応答の読み出し
  n = readline(con, buffer, LineMax, timeout);
  if (n <= 0) {
    return ReceiveTimeout;
  }

  // チェックサムの確認
  char checksum = (addSum(buffer, n - 1) & 0x3f) + 0x30;
  if (buffer[n - 1] != checksum) {
    return -3;
  }
  // ステータスの取得
  buffer[2] = '\0';
  int reply_code = strtol(buffer, NULL, 16);

  // 改行(1 byte)の読み捨て
  char last_ch;
  n = con->receive(&last_ch, 1, timeout);
  if (n != 1) {
    return -4;
  }
  if (! isLF(last_ch)) {
    // 文字が改行でなければ、データの可能性があるため書き戻す
    con->ungetc(last_ch);
  }

  // lines が NULL でなければ、最初に改行が来るまでを文字列データとして格納する
  if (lines != NULL) {
    while (true) {
      n = readline(con, buffer, LineMax, timeout);
      lines->push_back(buffer);
      if ((n == 1) && isLF(buffer[0])) {
        break;

      } else if (n <= 0) {
        // !!! reply_code を変更すべき
        break;
      }
    }
  }

  return reply_code;
}
