/*
-----------------------------------------------------------------------------
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 X10Device
  *  \brief Manage X10 CM11 device
  *  \
  *  \version 1.0
  *  \date may 2011
  */

#include "plugin.h"
#include "x10device.h"


void function_hook(unsigned char house,int unit,int function, int dim_level,struct x10_status_t *status)
{
  x10_log_event(house, unit, function, status);
  
  if (status->param)
  {
    X10Command* command = new X10Command(function, house, unit, dim_level);

    switch(function)
    {
      case X10_CMD_ALL_LIGHTS_ON:
        PostMessage(HScol, ALL_LIGHTS_ON_CB, (int)status->param, (LPARAM)command);
        break;

      case X10_CMD_ALL_UNITS_OFF:
        PostMessage(HScol, ALL_OFF_CB, (int)status->param, (LPARAM)command);
        break;

      case X10_CMD_ON:
        PostMessage(HScol, UNIT_ON_CB, (int)status->param, (LPARAM)command);
        break;

      case X10_CMD_OFF:
        PostMessage(HScol, UNIT_OFF_CB, (int)status->param, (LPARAM)command);
        break;

      case X10_CMD_DIM:
        PostMessage(HScol, UNIT_DIM_CB, (int)status->param, (LPARAM)command);
        break;

      case X10_CMD_BRIGHT:
        PostMessage(HScol, UNIT_BRIGHT_CB, (int)status->param, (LPARAM)command);
        break;

      default:
        delete(command);
        break;
      }
     
  }
}

X10Device::X10Device() : openutils::Thread()
{
  m_bConnect = false;
  m_bRunning = false;
  m_pxif = 0;
}

X10Device::X10Device(int port) : openutils::Thread()
{
  m_bConnect = false;
  m_bRunning = false;

  char buf[13];
  sprintf(buf, "\\\\.\\COM%i", port);
  m_pxif = x10_open(buf, x10_default_error, function_hook, 10000000, (void*)this);

  if (m_pxif)
  {
    m_bConnect = true;

    char buffer [33];
    itoa ((int)this,buffer,10);
    m_mutex.create(buffer);

    // Run thread
    this->start();
    m_bRunning = true;
  }
}

X10Device::~X10Device()
{
  m_bRunning = false;
  stop();

  x10_close(m_pxif);
  m_mutex.release();
  m_bConnect = false;
  m_pxif = 0;
}

bool X10Device::IsConnected()
{
  return m_bConnect;
}

void X10Device::run() 
{
  try 
  {
    while(m_bRunning)
    {
      if(m_pxif)
      {
			  x10_listen_to_events(m_pxif, 10000000);

        //copy the command list
        const std::list<X10Command> lCommandCpy = lCommand;
        
        //reset command list for new content
        lCommand.clear();

        std::list<X10Command>::const_iterator it;
        for (it=lCommandCpy.begin(); it != lCommandCpy.end(); it++)
        {
          X10Command xcommand = *it;
          x10_send_cmd(xcommand.HouseCode(), xcommand.UnitCode(), xcommand.Command(), xcommand.Value(), m_pxif);
        }
      }
    }
  }
  catch(openutils::ThreadException ex) 
  {
    MMechostr(MSKDEBUG,"error thread : %s \n",ex.getMessage().c_str()) ;
  }		
}

void X10Device::AllLightsOn(char houseCode)
{
  lCommand.push_back(X10Command(X10_CMD_ALL_LIGHTS_ON, houseCode));
}

void X10Device::AllOff(char houseCode)
{
  lCommand.push_back(X10Command(X10_CMD_ALL_UNITS_OFF, houseCode));
}

void X10Device::On(char houseCode, int unitCode)
{
  lCommand.push_back(X10Command(X10_CMD_ON, houseCode, unitCode));
}

void X10Device::Off(char houseCode, int unitCode)
{
  lCommand.push_back(X10Command(X10_CMD_OFF, houseCode, unitCode));
}

void X10Device::Dim(char houseCode, int unitCode, int value)
{
  lCommand.push_back(X10Command(X10_CMD_DIM, houseCode, unitCode, value));
}

void X10Device::Bright(char houseCode, int unitCode, int value)
{
  lCommand.push_back(X10Command(X10_CMD_BRIGHT, houseCode, unitCode, value));
}