#ifdef USE_AXFTEST_COMMAND_COMPLOG

#include <fstream>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <sstream>

#include "AXMScenarioTest.hpp"

// ケース終了識別ログ
const std::string AXMScenarioTest::mCaseEndStr("### Scenario CaseEnd ###");

// startIsrテスト回数
const int  AXMScenarioTest::mFrameIsrTestTime = 2000;

// startLoopbackテスト回数
const int  AXMScenarioTest::mLoopbackTestTime = 100;

// エラーメッセージ
const char AXMScenarioTest::mErrMsg[][50]={
//--------------------------------------------------//
 "test failed.",                                     /*00:テスト失敗(エラー要因未設定)*/
 "system error.",                                    /*01:システムエラー*/ 
 "message send failed.",                             /*02:メッセージ送信失敗*/
 "timer start failed.",                              /*03:タイマー開始失敗*/
 "timer stop failed.",                               /*04:タイマー停止失敗*/
 "scenario execution timeout.",                      /*05:シナリオ実行タイムアウト(テスト終端ログが検出できない)*/
 "priority check failed.",                           /*06:優先度チェック失敗(設定通りの優先度で動作していない)*/ 
 "isr frame interruption takes time too much.",      /*07:フレーム割り込みが規定時間内に処理されていない*/ 
 "isr frame stop was late.",                         /*08:フレーム割り込みが即座に停止できていない*/ 
 "abnormal received message.",                       /*09:受信データ不正*/ 
};

// テストケース名
const char AXMScenarioTest::mTestCaseName[][50]={
 /*00*/ "(no init)",
 /*01*/ "actorCommTest",
 /*02*/ "priSchedTest",
 /*03*/ "startIsrTest.",
 /*04*/ "stopIsrTest",
 /*05*/ "startLoopbackTest",
 /*06*/ "stopLoopbackTest",
};

// AXMScenarioTestインスタンス
AXMScenarioTest* AXMScenarioTest::m_scnObj = NULL;

AXMScenarioTest::AXMScenarioTest()
  :mFrameIsrStartMsec(0),
   mTestCaseNo(0)
{
}

AXMScenarioTest::~AXMScenarioTest()
{
}

AXMScenarioTest* AXMScenarioTest::getInstance()
{
  if(m_scnObj == NULL){
    static AXMScenarioTest obj;
    m_scnObj = &obj;
  }
  return m_scnObj;
}


void AXMScenarioTest::setTestCase(int caseno){
  mTestCaseNo   = caseno;
  std::cout << "setTestCase:" << mTestCaseName[mTestCaseNo] << std::endl;
  calcStartTime();
  return;
}

void AXMScenarioTest::writeLog(AXFLog *mlog, int result, int errcode){
  std::string dispMsg = getOutputMsg(mTestCaseNo, mTestCaseName[mTestCaseNo], calcEndTime(), result, errcode);
  mlog->write(AXFLOG_SCENARIO, dispMsg);
  return;
}

int AXMScenarioTest::getLapTime(){
  struct timespec endTp;
  clock_gettime(CLOCK_MONOTONIC, &endTp);
  int msec = (endTp.tv_sec * 1000) + (endTp.tv_nsec / 1000 / 1000);
  int retMsec = (msec - mFrameIsrStartMsec);
  return retMsec;
}

std::string AXMScenarioTest::getOutputMsg(
  int caseno, std::string casename, int time, int result, int errcode) {

  std::string outputMsg(mCaseEndStr);

  // テスト番号追加
  std::ostringstream casenoStr;
  casenoStr << caseno;
  outputMsg += ":" + casenoStr.str() + ":";

  // テスト名追加
  std::ostringstream casenoW3Str;
  casenoW3Str << std::setfill('0') << std::setw(3) << caseno;
  outputMsg += casenoW3Str.str() +"_"+ casename + ":";

  // テスト時間追加
  std::ostringstream timeStr;
  timeStr << time;
  outputMsg += timeStr.str() + ":";

  std::ostringstream errcodeStr;
  errcodeStr << errcode;

  // テスト結果追加
  switch(result){
    case RESULT_FAILED:
      outputMsg += "FAILED:";
      outputMsg += mErrMsg[errcode];
      outputMsg += "(errcode=" + errcodeStr.str() +")";
      break;
    case RESULT_SUCCESS:
      outputMsg += "SUCCESS";
      break;
    case RESULT_ERROR:
      outputMsg += "ERROR:";
      outputMsg += mErrMsg[errcode];
      outputMsg += "(errcode=" + errcodeStr.str() +")";
      break;
    case RESULT_SKIP:
      outputMsg += "SKIP";
      break;
  }
  return outputMsg;
}

void AXMScenarioTest::calcStartTime() {
  struct timespec startTp;
  clock_gettime(CLOCK_MONOTONIC, &startTp);
  mFrameIsrStartMsec = (startTp.tv_sec * 1000) + (startTp.tv_nsec / 1000 / 1000);
}

int AXMScenarioTest::calcEndTime() {
  int retMsec = getLapTime();

  std::ostringstream msecStr;
  msecStr  << retMsec;
  std::cout << "time:" << msecStr.str() << std::endl;
  return retMsec;
}
#endif /* USE_AXFTEST_COMMAND_COMPLOG */
