/*
 * Copyright (C) 2015 by the University of Southern California
 * $Id: client.cc 24038 2015-05-17 03:00:48Z liangzhu $
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * 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 General Public License for more details.                                      
 *
 * You should have received a copy of the GNU 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. 
 * 
 */

#include <iostream>
#include <assert.h>
#include <string.h>
#include <err.h>
#include "client.hh"
#include "global_var.h"
using namespace std;

client_t::client_t()
{
  init();
}

void client_t::init()
{
  type     = CONN_NONE;
  status   = STAT_NEW;
  s        = -1;
  svr_fd   = -1;
  ctx      = NULL;
  addr     = NULL;
  addr_len = 0;
  bev      = NULL;
  base     = NULL;
  map      = NULL;
  id_q     = NULL;
  recv_q = new safe_queue<net_msg *>(MAX_QSIZE);
  send_q = new safe_queue<net_msg *>(MAX_QSIZE);
  id_map = new safe_map<uint16_t, uint16_t>();
  pending_msg = new net_msg;
}

void client_t::copy(client_t *old)
{
  type     = old->type;
  s        = old->s;
  ctx      = old->ctx;
  addr     = old->addr;
  addr_len = old->addr_len;
  bev      = old->bev;
  base     = old->base;
  map      = old->map;
  svr_fd   = old->svr_fd;
  id_q     = old->id_q;
}

client_t::client_t(uint8_t tp, int skt,
		   struct sockaddr *a, socklen_t l,
		   struct bufferevent *ev_buf,
		   struct event_base *ev_base,
		   safe_map<int, client_t *> *m,
		   safe_queue<int> *q, int fd)
{
  init();
  copy_addr(a, l);
  type = tp;
  s = skt;
  bev = ev_buf;
  base = ev_base;
  map = m;
  id_q = q;
  svr_fd = fd;
}

client_t::client_t(client_t *c, uint8_t *cp, size_t l)
{
  copy(c);
}

client_t::~client_t()
{
  net_msg *item = NULL;
  
  while (recv_q != NULL && !recv_q->empty()){
    item = recv_q->pop();
    delete item;
  }
  delete recv_q;
  recv_q = NULL;
  
  while (send_q != NULL && !send_q->empty()){
    item = send_q->pop();
    delete item;
  }
  delete send_q;
  send_q = NULL;

  delete id_map;
  id_map = NULL;  

  delete addr;
  addr = NULL;

  delete pending_msg;
  pending_msg = NULL;
}

void client_t::enq_send(uint8_t *d, size_t l)
{
  net_msg *m = NULL;
  m = new net_msg();
  assert(m != NULL);
  m->copy(d, l, false);
  send_q->push(m);
}

void client_t::enq_recv(uint8_t *d, size_t l)
{
  net_msg *m = NULL;
  m = new net_msg();
  assert(m != NULL);
  m->copy(d, l, false);
  recv_q->push(m);
}

void client_t::copy_addr(struct sockaddr *a, socklen_t l)
{
  addr = new struct sockaddr;
  if (addr == NULL)
    err(1, "[error] memory allocation error, abort!");
  memcpy(addr, a, l);
  addr_len = l; //or = sizeof(struct sockaddr)?
}
