/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2010 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

You may alternatively use this source under the terms of a specific version of
the OpenSpace3D Unrestricted License provided you have obtained such a license from
I-maginer.
-----------------------------------------------------------------------------
*/

/*! \class SerialIO
  *  \brief Manage Serial device
  *  \
  *  \version 1.0
  *  \date jully 2011
  */

#include "plugin.h"
#include "serial.h"

SerialIO::SerialIO(int port, int baudRate, int parity, int byteSize, int stopBits) : openutils::Thread()
{
  m_bRunning = false;
  m_bConnected = false;
  m_bLastConState = true;
  m_buffer = new std::string("");
  m_port = port;
  m_baudrate = baudRate;
  m_parity = parity;
  m_byteSize = byteSize;
  if (stopBits == 1)
    m_stopBits = 1.5f;
  else if (stopBits == 2)
    m_stopBits = 2.0f;
  else
    m_stopBits = 1.0f;

  m_serial = new LSerie();

  try
  {
    char buffer [33];
    itoa ((int)this, buffer, 10);
    m_mutex.create(buffer);

    // Run thread
    this->start();
    m_bRunning = true;
  }
  catch (openutils::ThreadException ex)
  {
    MMechostr(MSKDEBUG, "Serial thread error : %s\n", ex.getMessage().c_str());
  }
}

SerialIO::~SerialIO()
{
  m_bRunning = false;
  stop();

  m_mutex.release();
  delete(m_buffer);
  SAFE_DELETE(m_serial);
}

bool SerialIO::IsConnected()
{
  return m_bConnected;
}

void SerialIO::run() 
{
  try 
  {
    while(m_bRunning)
    {
      // m_serial->isConnect() write A on port
      if(m_bConnected)
      {
        wait(m_mutex.getName().c_str());
        //write data
        if (m_buffer->size() > 0)
        {
          int nbsent = m_serial->sendData(m_buffer);
          if (nbsent == m_buffer->size())
            m_buffer->clear();
          else
            m_buffer->assign(m_buffer->substr(nbsent));
        }

        //read data
        std::string* buffer = new std::string("");
        int size = m_serial->receiveData(buffer);

        if (size == - 2)
        {
          m_bConnected = false;
          m_serial->closeCom();
          delete(buffer);
        }
        else if (size > 0)
          //read callback
          PostMessage(HScol, SERIAL_READ_CB, (int)this, (LPARAM)buffer);
        else
          delete(buffer);

        release(m_mutex.getName().c_str());
      }
      // try connect
      else
      {
        if (m_bLastConState)
        {
          m_bConnected = false;
          //disconnect callback
        }

        try
        {
          if (m_serial->open(m_port, m_baudrate, m_byteSize, m_parity, m_stopBits))
          {
            m_bLastConState = true;
            m_bConnected = true;
            //connect callback
          }
          else
          {
            m_serial->closeCom();
          }
        }
        catch (openutils::ThreadException ex)
        {
          MMechostr(MSKTRACE, "Serial connection failed : %s\n", ex.getMessage().c_str());
        }
      }
    }
  }
  catch(openutils::ThreadException ex) 
  {
    MMechostr(MSKDEBUG, "Serial thread error : %s \n", ex.getMessage().c_str()) ;
  }		
}

void SerialIO::Write(std::string data)
{
  wait(m_mutex.getName().c_str());
  m_buffer->append(data);
  release(m_mutex.getName().c_str());
}