#include "Subscription.h"
#include "Log.h"
#include "MString.h"
#include "TCPSession.h"
#include "TCPSocket.h"
#include <algorithm>

namespace core {

   Subscription::Subscription(coreutils::MString id, coreutils::MString mode)
       : id(id), mode(mode), owner(""), handler(NULL) {}

   Subscription::Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString mode)
       : id(id), mode(mode), owner(owner), handler(NULL) {}

   Subscription::Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString ownership, coreutils::MString mode, SubscriptionHandler *handler, coreutils::MString will, coreutils::MString timer)
       : id(id), ownership(ownership), mode(mode), owner(owner), handler(handler), will(will), timer(timer) {
      coreutils::Log(coreutils::LOG_DEBUG_3) << owner;
      coreutils::Log(coreutils::LOG_DEBUG_3) << will;
      subscriptionOwner(owner, will);
   }

   Subscription::~Subscription() {

      std::stringstream out;

      out << "cancel:" << id << std::endl;
      for (auto subscriber : subscribers) {
         subscriber->write(out.str());
      }
   }

   int Subscription::subscribe(TCPSession &session) {
      if (handler)
	handler->onSubscribe(session, this);
      else
	onSubscribe(session);
      subscribers.push_back(&session);  
      return 1;
   }

   int Subscription::unsubscribe(TCPSession &session) {
      for (auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber) 
	if (*subscriber == &session) {
	   subscribers.erase(subscriber++);
	   return 1;
	}
      return 0;
   }

   bool Subscription::subscriptionOwner(coreutils::MString alias, coreutils::MString ownerSelection) {
      subscriptionOwners = alias;
      selectionOfOwnerForSubscription = ownerSelection;
      coreutils::Log(coreutils::LOG_DEBUG_1) << "Owner of Subscription: " << subscriptionOwners;
      coreutils::Log(coreutils::LOG_DEBUG_1) << "Will of Subscription: " << selectionOfOwnerForSubscription;
      return true;
   }

   int Subscription::process(coreutils::ZString &request, std::stringstream &out, TCPSession &session) {
      if (handler)
         handler->process(request, out, session, this);
      else
         out << "event:" << request[1] << ":" << request[2] << std::endl;
      return 1;
   }

   int Subscription::event(std::stringstream &out) {
      for (auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber) 
	(*subscriber)->write(out.str());      
      return 1;
   }

   bool Subscription::ifSubscriber(TCPSession &session) {
      return (std::find(subscribers.begin(), subscribers.end(), &session) != subscribers.end());
   }

   int Subscription::onSubscribe(TCPSession &session) {
      return 0;
   }

   bool Subscription::subInvite(TCPSession &session) {
      return 0;
   }

   void Subscription::sendToAll(std::stringstream &data, TCPSession &sender) {
      for (auto session : subscribers)
	if (session != &sender)
	  session->write(data.str());
      data.str("");
   }

}
