/*!
  \file
  \brief SH7045 のスタブ

  \author Satofumi KAMIMURA

  $Id: stub_sh7045.cpp 1140 2009-07-13 21:41:41Z satofumi $
*/

#include "stub_sh7045.h"
#include "sformat_receiver.h"
#include "TcpipAccepter.h"
#include "TcpipSocket.h"
#include <iostream>
#include <cstdlib>

extern void sci_initialize(qrk::Connection* connection);

using namespace qrk;
using namespace std;


namespace
{
  bool receive_ch(Connection* connection, char expected_ch, int timeout)
  {
    char recv_ch;
    int n = connection->receive(&recv_ch, 1, timeout);
    return ((n != 1) || (recv_ch != expected_ch)) ? false : true;
  }


  void exitWithError(const string& error_message)
  {
    cout << error_message << endl;
    exit(1);
  }


  void stubFztat(Connection* connection, int timeout)
  {
    if (! receive_ch(connection, 0x00, timeout)) {
      exitWithError("sh7045 stub error: no 1st 0x00.");
    }
    char send_ch = 0x00;
    connection->send(&send_ch, 1);

    if (! receive_ch(connection, 0x55, timeout)) {
      exitWithError("sh7045 stub error: no 0x55.");
    }
    send_ch = 0xaa;
    connection->send(&send_ch, 1);

    char size_bytes[2];
    if (connection->receive(size_bytes, 2, timeout) != 2) {
      exitWithError("sh7045 stub error: no size data.");
    }
    connection->send(size_bytes, 2);

    size_t program_size =
      static_cast<unsigned short>(((size_bytes[0] << 8) & 0xff00)
                                  | (size_bytes[1] & 0xff));
    for (size_t i = 0; i < program_size; ++i) {
      char ch;
      int n = connection->receive(&ch, 1, timeout);
      if (n > 0) {
        connection->send(&ch, 1);
      }
    }
    send_ch = 0xaa;
    connection->send(&send_ch, 1);
  }


  void stubWriting(Connection* connection)
  {
    sci_initialize(connection);
    sformat_handler();
  }
}


int stub_sh7045(void* port)
{
  enum { Timeout = 100 };

  long stub_port = *static_cast<long*>(port);
  static_cast<void>(stub_port);

  // サーバの起動
  TcpipAccepter server;
  if (! server.activate(stub_port)) {
    string error_message = string("sh7045 stub error: ") + server.what();
    exitWithError(error_message);
  }
  TcpipSocket* client = server.accept(Timeout);
  if (! client) {
    exitWithError("sh7045 stub error: no connection.");
  }

  // F-ZTAT の動作
  stubFztat(client, Timeout);

  // 独自プロトコルの動作
  stubWriting(client);

  return 0;
}
