/*
 * Copyright (C) 2013 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <hardware/bluetooth.h>

#include "if-main.h"
#include "../hal-utils.h"

const btpan_interface_t *if_pan = NULL;

typedef int btpan_role_t;

SINTMAP(btpan_role_t, -1, "(unknown)")
	DELEMENT(BTPAN_ROLE_NONE),
	DELEMENT(BTPAN_ROLE_PANNAP),
	DELEMENT(BTPAN_ROLE_PANU),
ENDMAP

SINTMAP(btpan_connection_state_t, -1, "(unknown)")
	DELEMENT(BTPAN_STATE_CONNECTED),
	DELEMENT(BTPAN_STATE_CONNECTING),
	DELEMENT(BTPAN_STATE_DISCONNECTED),
	DELEMENT(BTPAN_STATE_DISCONNECTING),
ENDMAP

SINTMAP(btpan_control_state_t, -1, "(unknown)")
	DELEMENT(BTPAN_STATE_ENABLED),
	DELEMENT(BTPAN_STATE_DISABLED),
ENDMAP

static void control_state_cb(btpan_control_state_t state, bt_status_t error,
					int local_role, const char *ifname)
{
	haltest_info("%s: state=%s error=%s local_role=%s ifname=%s\n",
			__func__, btpan_control_state_t2str(state),
			bt_status_t2str(error), btpan_role_t2str(local_role),
			ifname);
}

static char last_used_addr[MAX_ADDR_STR_LEN];

static void connection_state_cb(btpan_connection_state_t state,
				bt_status_t error, const bt_bdaddr_t *bd_addr,
				int local_role, int remote_role)
{
	haltest_info("%s: state=%s error=%s bd_addr=%s local_role=%s remote_role=%s\n",
			__func__, btpan_connection_state_t2str(state),
			bt_status_t2str(error),
			bt_bdaddr_t2str(bd_addr, last_used_addr),
			btpan_role_t2str(local_role),
			btpan_role_t2str(remote_role));
}

static btpan_callbacks_t pan_cbacks = {
	.size = sizeof(pan_cbacks),
	.control_state_cb = control_state_cb,
	.connection_state_cb = connection_state_cb
};

static void init_p(int argc, const char **argv)
{
	RETURN_IF_NULL(if_pan);

	EXEC(if_pan->init, &pan_cbacks);
}

/* enable */

static void enable_c(int argc, const char **argv, enum_func *enum_func,
								void **user)
{
	if (argc == 3) {
		*user = TYPE_ENUM(btpan_role_t);
		*enum_func = enum_defines;
	}
}

static void enable_p(int argc, const char **argv)
{
	int local_role;

	RETURN_IF_NULL(if_pan);

	/* local role */
	if (argc < 3) {
		haltest_error("No local mode specified\n");
		return;
	}
	local_role = str2btpan_role_t(argv[2]);
	if (local_role == -1)
		local_role = atoi(argv[2]);

	EXEC(if_pan->enable, local_role);
}

/* get_local_role */

static void get_local_role_p(int argc, const char **argv)
{
	int local_role;

	RETURN_IF_NULL(if_pan);

	local_role = if_pan->get_local_role();
	haltest_info("local_role: %s\n", btpan_role_t2str(local_role));
}

/* connect */

static void connect_c(int argc, const char **argv, enum_func *enum_func,
								void **user)
{
	if (argc == 3) {
		*user = NULL;
		*enum_func = enum_devices;
	} else if (argc == 4 || argc == 5) {
		*user = TYPE_ENUM(btpan_role_t);
		*enum_func = enum_defines;
	}
}

static void connect_p(int argc, const char **argv)
{
	bt_bdaddr_t addr;
	int local_role;
	int remote_role;

	RETURN_IF_NULL(if_pan);
	VERIFY_ADDR_ARG(2, &addr);

	/* local role */
	if (argc < 4) {
		haltest_error("No local mode specified\n");
		return;
	}
	local_role = str2btpan_role_t(argv[3]);
	if (local_role == -1)
		local_role = atoi(argv[3]);

	/* remote role */
	if (argc < 5) {
		haltest_error("No remote mode specified\n");
		return;
	}
	remote_role = str2btpan_role_t(argv[4]);
	if (remote_role == -1)
		remote_role = atoi(argv[4]);

	EXEC(if_pan->connect, &addr, local_role, remote_role);
}

/* disconnect */

static void disconnect_c(int argc, const char **argv, enum_func *enum_func,
								void **user)
{
	if (argc == 3) {
		*user = last_used_addr;
		*enum_func = enum_one_string;
	}
}

static void disconnect_p(int argc, const char **argv)
{
	bt_bdaddr_t addr;

	RETURN_IF_NULL(if_pan);
	VERIFY_ADDR_ARG(2, &addr);

	EXEC(if_pan->disconnect, &addr);
}

/* cleanup */

static void cleanup_p(int argc, const char **argv)
{
	RETURN_IF_NULL(if_pan);

	EXECV(if_pan->cleanup);
	if_pan = NULL;
}

static struct method methods[] = {
	STD_METHOD(init),
	STD_METHODCH(connect, "<addr> <local_role> <remote_role>"),
	STD_METHODCH(enable, "<local_role>"),
	STD_METHOD(get_local_role),
	STD_METHODCH(disconnect, "<addr>"),
	STD_METHOD(cleanup),
	END_METHOD
};

const struct interface pan_if = {
	.name = "pan",
	.methods = methods
};
