/**
 * ------------------------------------------------------------------------
 *
 * Copyright (c) 2018, Ericsson Canada
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of Ericsson Canada nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Version 0.1: Jon Maloy, 2018
 *
 * ------------------------------------------------------------------------
 */
package com.tipcj;

/**
 * TODO
 */
import java.io.*;
import java.nio.*;
import java.lang.reflect.Field;

/**
 * @author Hoang Le (hoang.h.le@dektech.com.au)
 *
 */
final class TipcBaseApi {

	/**
	 * Some helper method
	 */
	protected native int tipc_own_node();
	protected native String tipc_linkname(long peer, long bearerid);

	/**
	 * Socket: - 'Rejectable': sent messages will return if rejected at
	 * destination
	 */
	protected native int tipc_socket(int sk_type);

	protected native int tipc_sock_non_block(int sd);

	protected native int tipc_sock_rejectable(int sd);

	protected native int tipc_close(int sd);

	protected native int tipc_sockaddr(int sd, TipcAddr addr);

	protected native int tipc_bind(int sd, long type, long lower, long upper, long scope);

	protected native int tipc_unbind(int sd, long type, long lower, long upper);

	protected native int tipc_connect(int sd, TipcAddr dst);

	protected native int tipc_listen(int sd, long backlog);

	protected native int tipc_accept(int sd, TipcAddr src);

	protected native int tipc_join(int sd, TipcAddr member, boolean events, boolean loopback);

	protected native int tipc_leave(int sd);

	/**
	 * Messaging: - NULL pointer parameters are always accepted - tipc_sendto()
	 * to an accepting socket initiates two-way connect - If no err pointer
	 * given, tipc_recvfrom() returns 0 on rejected message - If (*err != 0) buf
	 * contains a potentially truncated rejected message - Group event:
	 * tipc_recvfrom() returns 0; err == 0/-1 indicates up/down
	 */
	protected native int tipc_recvfrom(int sd, ByteBuffer buf, int length, TipcAddr socket, TipcAddr member,
			java.lang.Integer err);

	protected native int tipc_recv(int sd, ByteBuffer buf, int length, boolean waitall);

	protected native int tipc_sendmsg(int sd, ByteBuffer msg, int length);

	protected native int tipc_sendto(int sd, ByteBuffer msg, int length, TipcAddr dst);

	protected native int tipc_send(int sd, ByteBuffer msg, int length);

	protected native int tipc_mcast(int sd, ByteBuffer msg, int length, TipcAddr dst);

	/** Topology Server:
	 * - Expiration time in [ms]
	 * - If (expire < 0) subscription never expires
	 */
	protected native int tipc_topsrv_conn(long topsrv_node);
	protected native int tipc_srv_subscr(int sd, long type, long lower, long upper, boolean all, int expire);
	protected native int tipc_srv_evt(int sd, TipcAddr srv, TipcAddr addr, java.lang.Integer up, java.lang.Integer expired);
	protected native boolean tipc_srv_wait(TipcAddr srv, int expire);

	/**
	 * C poll API wrapper
	 */
	protected native int tipc_poll(int fd, short events, java.lang.Integer revents, int timeout);
	protected native int tipc_pollset(int[] fds, short[] events, java.lang.Integer[] revents, int timeout);

	static {

		String libSysPath = System.getProperty("java.library.path");
		libSysPath += System.getProperty("user.dir") + File.pathSeparator + ".libs";
		System.setProperty("java.library.path", libSysPath);

		try {
			/**
			 * Work-around to make sure java.library.path updated at runtime
			 */
			Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
			fieldSysPath.setAccessible(true);
			fieldSysPath.set(null, null);
		} catch (Exception e) {
		}

		/**
		 * Load native library in static initializer of class
		 */
		try {
			System.loadLibrary("tipcj");
		} catch (UnsatisfiedLinkError e) {
			System.out.println("Specific -Djava.library.path where libtipcj.so is located");
		}
	}

	/**
	 * TODO:
	 */
	private static final TipcBaseApi instance = new TipcBaseApi();

	/**
	 * TODO:
	 */
	public static int OwnNode = 0;

	/**
	 * Non expose this class
	 */
	private TipcBaseApi() {}

	/**
	 *
	 * @return
	 */
	protected static TipcBaseApi getInstance() {
		return instance;
	}
}
