/*
 * Client program copyright (C) 2009 - 2013 H.Niwa 
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, 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 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

#ifndef __MINGW32__ 

#include "config.h"
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>

#include <string>
#include <complex>

#include "syserr.h"
#include "bin_node.h"
#include "gc.h"
#include "var.h"
#include "pred.h"
#include "context.h"
#include "unify.h"
#include "builtin.h"
#include "sysmodule.h"

#include "proc.h"
#include "client.h"


int ProcClient(Node* val, int n, int status, char* sockname)
{
	int fd;
	struct sockaddr_un addr;
	char buf[1024+1];

	fd = socket(PF_UNIX, SOCK_STREAM, 0);
	if (fd < 0) {
		syserr("ProcClient error : socket \n");
		return 0;
	}

	bzero((char *) &addr, sizeof(addr));

	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
	addr.sun_path[sizeof(addr.sun_path)-1] = 0;

	while (connect(fd, (struct sockaddr *) &addr,
			sizeof(addr.sun_family) + strlen(sockname)) < 0) {
		usleep(1);
	}

	if (val->kind() != ATOM) {
		val = Nil;
	}

	std::string s;
	((Atom*)val)->toString(s);

	long double real, img;
	int floatflg = ((Atom*)val)->FloatFlag();
	if (floatflg) {
		((Atom*)val)->toFloat(real);
		((Atom*)val)->toImage(img);
	}
	
	int pktlen = s.length()+sizeof(int)*4;
	*(int*)buf = pktlen;
	*(int*)(buf+sizeof(int)) = n;
	*(int*)(buf+sizeof(int)*2) = status;
	*(int*)(buf+sizeof(int)*3) = floatflg;

	if (floatflg) {
		*(long double*)(buf+sizeof(int)*4) = real;
		*(long double*)(buf+sizeof(int)*4+sizeof(long double)) = img;
	} else {
		strncpy(buf+sizeof(int)*4, s.c_str(), 1024-sizeof(int)*4);
	}
	buf[1024] = 0;
	
	int rc, retry;
	for (retry = 0; retry < MAXCORE; retry++) {
		rc = send(fd, buf, 1024, 0);
		if (rc >= 0) {
			break;
		}
	}
	if (rc < 0) {
		shutdown(fd, SHUT_RDWR);
		close(fd);
//		syserr("ProcClient : send error \n");
		return 0;
	}

//printf("ProcClient send \n");
//printf("buf %s \n", buf+8);

	int i, l = s.length();
	for (i = 1024; i < l; i+=1024) {
		strncpy(buf, s.c_str(), 1024);

		rc = send(fd, buf, 1024, 0);
		if (rc < 0) {
			shutdown(fd, SHUT_RDWR);
			close(fd);
			syserr("ProcClient : send error \n");
			return 0;
		}
//printf(" ...buf %s \n", buf);
	}
	
//printf("client   buf %s \n", buf+8);

	shutdown(fd, SHUT_RDWR);
	close(fd);

	return 1;
}

#endif /* __MINGW32__ */
