#include "MultiTopic_Sender_exec.h"
#include "tao/ORB_Core.h"
#include "ace/Reactor.h"

namespace CIAO_Shapes_Sender_Impl
{

  pulse_Generator::pulse_Generator (Sender_exec_i &callback)
    : pulse_callback_ (callback)
  {
  }

  pulse_Generator::~pulse_Generator ()
  {
  }

  int
  pulse_Generator::handle_timeout (const ACE_Time_Value &, const void *)
  {
    this->pulse_callback_.tick ();
    return 0;
  }

  Sender_exec_i::Sender_exec_i (void)
    : rate_ (0),
      max_x_ (0),
      max_y_ (0),
      max_size_ (0),
      resize_shape_ (false),
      TypeOfShape (SHAPE_TYPE_SQUARE)
  {
    ACE_NEW_THROW_EX (this->ticker_,
                      pulse_Generator (*this),
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->square_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->triangle_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->circle_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
  }

  Sender_exec_i::~Sender_exec_i (void)
  {
    delete this->ticker_;
    delete this->square_;
    delete this->triangle_;
    delete this->circle_;
  }

  ACE_Reactor*
  Sender_exec_i::reactor (void)
  {
    ACE_Reactor* reactor = 0;
    ::CORBA::Object_var ccm_object =
      this->ciao_context_->get_CCM_object();
    if (! ::CORBA::is_nil (ccm_object.in ()))
      {
        ::CORBA::ORB_var orb = ccm_object->_get_orb ();
        if (! ::CORBA::is_nil (orb.in ()))
          {
            reactor = orb->orb_core ()->reactor ();
          }
      }
    if (reactor == 0)
      {
        throw ::CORBA::INTERNAL ();
      }
    return reactor;
  }

  void
  Sender_exec_i::tick ()
    {
      try
        {
          ::Shapes::DDS_Typed::Writer_var writer;
          if (this->TypeOfShape == SHAPE_TYPE_SQUARE)
            {
              writer = this->ciao_context_->get_connection_info_write_sq_data ();
            }
          else if (this->TypeOfShape == SHAPE_TYPE_TRIANGLE)
            {
              writer = this->ciao_context_->get_connection_info_write_tr_data ();
            }
          else if (this->TypeOfShape == SHAPE_TYPE_CIRCLE)
            {
              writer = this->ciao_context_->get_connection_info_write_cl_data ();
            }
          if (::CORBA::is_nil (writer.in ()))
            {
              ACE_ERROR ((LM_ERROR, "Sender_exec_i::tick () - "
                        "ERROR: Unable to get connection to writer\n"));
              return;
            }

         if (this->TypeOfShape == SHAPE_TYPE_SQUARE)
          {
            this->TypeOfShape = SHAPE_TYPE_TRIANGLE;
            writer->write_one (*square_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Square for <%C> %u:%u:%u\n"),
                this->square_->color.in (),
                this->square_->x,
                this->square_->y,
                this->square_->shapesize));
          }
        else if (this->TypeOfShape == SHAPE_TYPE_TRIANGLE)
          {
            this->TypeOfShape = SHAPE_TYPE_CIRCLE;
            writer->write_one (*triangle_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Triangle for <%C> %u:%u:%u\n"),
                this->triangle_->color.in (),
                this->triangle_->x,
                this->triangle_->y,
                this->triangle_->shapesize));
          }
        else if (this->TypeOfShape == SHAPE_TYPE_CIRCLE)
          {
            this->TypeOfShape = SHAPE_TYPE_SQUARE;
            writer->write_one (*circle_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Circle for <%C> %u:%u:%u\n"),
                this->circle_->color.in (),
                this->circle_->x,
                this->circle_->y,
                this->circle_->shapesize));
           }
        }
      catch (const CCM_DDS::NonExistent& )
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("Shape_info for <%C> not updated: <%C> didn't exist.\n"),
                      this->square_->color.in (), this->square_->color.in ()));
        }
      catch (const CCM_DDS::InternalError& )
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("Internal Error while updating Shape_info for <%C>.\n"),
                      this->square_->color.in ()));
        }
    }

  ::CORBA::ULong
  Sender_exec_i::rate (void)
  {
    return this->rate_;
  }

  void
  Sender_exec_i::rate (
    const ::CORBA::ULong rate)
  {
    this->rate_ = rate;
  }

  ::CORBA::UShort
  Sender_exec_i::max_x (void)
  {
    return this->max_x_;
  }

  void
  Sender_exec_i::max_x (
    const ::CORBA::UShort max_x)
  {
    this->max_x_ = max_x;
  }

  ::CORBA::UShort
  Sender_exec_i::max_y (void)
  {
    return this->max_y_;
  }

  void
  Sender_exec_i::max_y (
    const ::CORBA::UShort max_y)
  {
    this->max_y_ = max_y;
  }

  ::CORBA::UShort
  Sender_exec_i::max_size (void)
  {
    return this->max_size_;
  }

  void
  Sender_exec_i::max_size (
    const ::CORBA::UShort max_size)
  {
    this->max_size_ = max_size;
  }

  ::CORBA::Boolean
  Sender_exec_i::resize_shape (void)
  {
    return this->resize_shape_;
  }

  void
  Sender_exec_i::resize_shape (
    const ::CORBA::Boolean resize_shape)
  {
    this->resize_shape_ = resize_shape;
  }

  void
  Sender_exec_i::start (void)
  {

    long const usec = 1000000 / this->rate_;

    if (this->reactor ()->schedule_timer (
                this->ticker_,
                0,
                ACE_Time_Value (0, usec),
                ACE_Time_Value (0, usec)) == -1)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Sender_exec_i::start : ")
                             ACE_TEXT ("Error scheduling timer")));
    }
  }

  void
  Sender_exec_i::stop (void)
  {
    try
      {
        this->reactor ()->cancel_timer (this->ticker_);
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("Sender_exec_i::stop : Timer canceled.\n")));
        delete this->ticker_;
        delete this->square_;
        delete this->triangle_;
        delete this->circle_;
      }
    catch (...)
      {
        ACE_ERROR ((LM_ERROR, "Sender_exec_i::stop - "
                  "ERROR: unexpected exception caught while shutting down.\n"));
      }
  }

  void
  Sender_exec_i::set_session_context (
    ::Components::SessionContext_ptr ctx)
  {
    this->ciao_context_ =
      ::Shapes::CCM_Sender_Context::_narrow (ctx);

    if ( ::CORBA::is_nil (this->ciao_context_.in ()))
      {
        throw ::CORBA::INTERNAL ();
      }
  }

  void
  Sender_exec_i::configuration_complete (void)
  {
  }

  void
  Sender_exec_i::ccm_activate (void)
  {
    this->square_->x = ACE_OS::rand () % this->max_x_;
    this->square_->y = ACE_OS::rand () % this->max_y_;
    this->square_->shapesize = max_size_;
    this->square_->color = CORBA::string_dup("GREEN");

    this->triangle_->x = ACE_OS::rand () % this->max_x_;
    this->triangle_->y = ACE_OS::rand () % this->max_y_;
    this->triangle_->shapesize = max_size_;
    this->triangle_->color = CORBA::string_dup("YELLOW");

    this->circle_->x = ACE_OS::rand () % this->max_x_;
    this->circle_->y = ACE_OS::rand () % this->max_y_;
    this->circle_->shapesize = max_size_;
    this->circle_->color = CORBA::string_dup("BLUE");

    this->start ();
  }

  void
  Sender_exec_i::ccm_passivate (void)
  {
     this->stop ();
  }

  void
  Sender_exec_i::ccm_remove (void)
  {

  }

  extern "C"  ::Components::EnterpriseComponent_ptr
  create_Shape_Sender_Impl (void)
  {

    ::Components::EnterpriseComponent_ptr retval =
      ::Components::EnterpriseComponent::_nil ();

    ACE_NEW_NORETURN (
      retval,
      Sender_exec_i);

    return retval;
  }
}
// -*- C++ -*-
/**
 * Code generated by the The ACE ORB (TAO) IDL Compiler v1.8.2
 * TAO and the TAO IDL Compiler have been developed by:
 *       Center for Distributed Object Computing
 *       Washington University
 *       St. Louis, MO
 *       USA
 *       http://www.cs.wustl.edu/~schmidt/doc-center.html
 * and
 *       Distributed Object Computing Laboratory
 *       University of California at Irvine
 *       Irvine, CA
 *       USA
 * and
 *       Institute for Software Integrated Systems
 *       Vanderbilt University
 *       Nashville, TN
 *       USA
 *       http://www.isis.vanderbilt.edu/
 *
 * Information about TAO is available at:
 *     http://www.dre.vanderbilt.edu/~schmidt/TAO.html
 **/

#include "MultiTopic_Sender_exec.h"
#include "tao/ORB_Core.h"
#include "ace/Reactor.h"

namespace CIAO_Shapes_Sender_Impl
{
  //============================================================
  // pulse_Generator
  //============================================================
  pulse_Generator::pulse_Generator (Sender_exec_i &callback)
    : pulse_callback_ (callback)
  {
  }

  pulse_Generator::~pulse_Generator ()
  {
  }

  int
  pulse_Generator::handle_timeout (const ACE_Time_Value &, const void *)
  {
    this->pulse_callback_.tick ();
    return 0;
  }


   /**
   * Component Executor Implementation Class: Sender_exec_i
   */
  Sender_exec_i::Sender_exec_i (void)
    : rate_ (0),
      max_x_ (0),
      max_y_ (0),
      max_size_ (0),
      resize_shape_ (false),
      TypeOfShape (SHAPE_TYPE_SQUARE)
  {
    ACE_NEW_THROW_EX (this->ticker_,
                      pulse_Generator (*this),
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->square_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->triangle_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
    ACE_NEW_THROW_EX (this->circle_,
                      ShapeType,
                      ::CORBA::NO_MEMORY ());
  }

  Sender_exec_i::~Sender_exec_i (void)
  {
    delete this->ticker_;
    delete this->square_;
    delete this->triangle_;
    delete this->circle_;
  }

  // Supported operations and attributes.
  ACE_Reactor*
  Sender_exec_i::reactor (void)
  {
    ACE_Reactor* reactor = 0;
    ::CORBA::Object_var ccm_object =
      this->ciao_context_->get_CCM_object();
    if (! ::CORBA::is_nil (ccm_object.in ()))
      {
        ::CORBA::ORB_var orb = ccm_object->_get_orb ();
        if (! ::CORBA::is_nil (orb.in ()))
          {
            reactor = orb->orb_core ()->reactor ();
          }
      }
    if (reactor == 0)
      {
        throw ::CORBA::INTERNAL ();
      }
    return reactor;
  }

  void
  Sender_exec_i::tick ()
    {
      try
        {
          ::Shapes::DDS_Typed::Writer_var writer;
          if (this->TypeOfShape == SHAPE_TYPE_SQUARE)
            {
              writer = this->ciao_context_->get_connection_info_write_sq_data ();
            }
          else if (this->TypeOfShape == SHAPE_TYPE_TRIANGLE)
            {
              writer = this->ciao_context_->get_connection_info_write_tr_data ();
            }
          else if (this->TypeOfShape == SHAPE_TYPE_CIRCLE)
            {
              writer = this->ciao_context_->get_connection_info_write_cl_data ();
            }
          if (::CORBA::is_nil (writer.in ()))
            {
              ACE_ERROR ((LM_ERROR, "Sender_exec_i::tick () - "
                        "ERROR: Unable to get connection to writer\n"));
              return;
            }

         if (this->TypeOfShape == SHAPE_TYPE_SQUARE)
          {
            this->TypeOfShape = SHAPE_TYPE_TRIANGLE;
            writer->write_one (*square_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Square for <%C> %u:%u:%u\n"),
                this->square_->color.in (),
                this->square_->x,
                this->square_->y,
                this->square_->shapesize));
          }
        else if (this->TypeOfShape == SHAPE_TYPE_TRIANGLE)
          {
            this->TypeOfShape = SHAPE_TYPE_CIRCLE;
            writer->write_one (*triangle_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Triangle for <%C> %u:%u:%u\n"),
                this->triangle_->color.in (),
                this->triangle_->x,
                this->triangle_->y,
                this->triangle_->shapesize));
          }
        else if (this->TypeOfShape == SHAPE_TYPE_CIRCLE)
          {
            this->TypeOfShape = SHAPE_TYPE_SQUARE;
            writer->write_one (*circle_, ::DDS::HANDLE_NIL);
            ACE_DEBUG ((LM_DEBUG,
                ACE_TEXT ("UPDATED Shape_info Circle for <%C> %u:%u:%u\n"),
                this->circle_->color.in (),
                this->circle_->x,
                this->circle_->y,
                this->circle_->shapesize));
           }
        }
      catch (const CCM_DDS::NonExistent& )
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("Shape_info for <%C> not updated: <%C> didn't exist.\n"),
                      this->square_->color.in (), this->square_->color.in ()));
        }
      catch (const CCM_DDS::InternalError& )
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("Internal Error while updating Shape_info for <%C>.\n"),
                      this->square_->color.in ()));
        }
    }

  // Component attributes and port operations.

  ::CORBA::ULong
  Sender_exec_i::rate (void)
  {
    return this->rate_;
  }

  void
  Sender_exec_i::rate (
    const ::CORBA::ULong rate)
  {
    this->rate_ = rate;
  }

  ::CORBA::UShort
  Sender_exec_i::max_x (void)
  {
    return this->max_x_;
  }

  void
  Sender_exec_i::max_x (
    const ::CORBA::UShort max_x)
  {
    this->max_x_ = max_x;
  }

  ::CORBA::UShort
  Sender_exec_i::max_y (void)
  {
    return this->max_y_;
  }

  void
  Sender_exec_i::max_y (
    const ::CORBA::UShort max_y)
  {
    this->max_y_ = max_y;
  }

  ::CORBA::UShort
  Sender_exec_i::max_size (void)
  {
    return this->max_size_;
  }

  void
  Sender_exec_i::max_size (
    const ::CORBA::UShort max_size)
  {
    this->max_size_ = max_size;
  }

  ::CORBA::Boolean
  Sender_exec_i::resize_shape (void)
  {
    return this->resize_shape_;
  }

  void
  Sender_exec_i::resize_shape (
    const ::CORBA::Boolean resize_shape)
  {
    this->resize_shape_ = resize_shape;
  }


  void
  Sender_exec_i::start (void)
  {
    // calculate the interval time
    long const usec = 1000000 / this->rate_;

    if (this->reactor ()->schedule_timer (
                this->ticker_,
                0,
                ACE_Time_Value (0, usec),
                ACE_Time_Value (0, usec)) == -1)
    {
      ACE_ERROR ((LM_ERROR, ACE_TEXT ("Sender_exec_i::start : ")
                             ACE_TEXT ("Error scheduling timer")));
    }
  }

  void
  Sender_exec_i::stop (void)
  {
    try
      {
        this->reactor ()->cancel_timer (this->ticker_);
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("Sender_exec_i::stop : Timer canceled.\n")));
        delete this->ticker_;
        delete this->square_;
        delete this->triangle_;
        delete this->circle_;
      }
    catch (...)
      {
        ACE_ERROR ((LM_ERROR, "Sender_exec_i::stop - "
                  "ERROR: unexpected exception caught while shutting down.\n"));
      }
  }

  // Operations from Components::SessionComponent.
  void
  Sender_exec_i::set_session_context (
    ::Components::SessionContext_ptr ctx)
  {
    this->ciao_context_ =
      ::Shapes::CCM_Sender_Context::_narrow (ctx);

    if ( ::CORBA::is_nil (this->ciao_context_.in ()))
      {
        throw ::CORBA::INTERNAL ();
      }
  }

  void
  Sender_exec_i::configuration_complete (void)
  {
  }

  void
  Sender_exec_i::ccm_activate (void)
  {
    this->square_->x = ACE_OS::rand () % this->max_x_;
    this->square_->y = ACE_OS::rand () % this->max_y_;
    this->square_->shapesize = max_size_;
    this->square_->color = CORBA::string_dup("GREEN");

    this->triangle_->x = ACE_OS::rand () % this->max_x_;
    this->triangle_->y = ACE_OS::rand () % this->max_y_;
    this->triangle_->shapesize = max_size_;
    this->triangle_->color = CORBA::string_dup("YELLOW");

    this->circle_->x = ACE_OS::rand () % this->max_x_;
    this->circle_->y = ACE_OS::rand () % this->max_y_;
    this->circle_->shapesize = max_size_;
    this->circle_->color = CORBA::string_dup("BLUE");

    this->start ();
  }

  void
  Sender_exec_i::ccm_passivate (void)
  {
     this->stop ();
  }

  void
  Sender_exec_i::ccm_remove (void)
  {
    /* Your code here. */
  }

  extern "C"  ::Components::EnterpriseComponent_ptr
  create_Shape_Sender_Impl (void)
  {

    ::Components::EnterpriseComponent_ptr retval =
      ::Components::EnterpriseComponent::_nil ();

    ACE_NEW_NORETURN (
      retval,
      Sender_exec_i);

    return retval;
  }
}
