/*
 * CINELERRA
 * Copyright (C) 2016-2020 William Morrow
 *
 * 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include "keys.h"
#include "mwindow.h"
#include "mwindowgui.h"
#include "androidcontrol.h"
#include "preferences.h"


int AndroidControl::open(unsigned short port)
{
	sockfd = socket(PF_INET,SOCK_DGRAM,0);
	if( sockfd < 0 ) { perror("socket:"); return -1; }

	struct linger lgr;
	lgr.l_onoff = 0;
	lgr.l_linger = 0;

	if( setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &lgr, sizeof(lgr)) < 0 ) {
		perror("setlinger:");
		return -1;
	}

	struct sockaddr_in sadr;
	memset(&sadr,0,sizeof(sadr));
	sadr.sin_family = AF_INET;
	sadr.sin_port = htons(port);
	sadr.sin_addr.s_addr = 0;

	if( bind(sockfd,(struct sockaddr *)&sadr,sizeof(sadr)) < 0 ) {
		perror("bind:");
		return -1;
	}

	return 0;
}

void AndroidControl::close()
{
	if( sockfd >= 0 ) {
		::close(sockfd);
		sockfd = -1;
	}
}

AndroidControl::AndroidControl(MWindowGUI *mwindow_gui)
 : Thread(1, 0, 0)
{
	this->mwindow_gui = mwindow_gui;
	Thread::start();
	done = -1;
	sockfd = -1;
	msg = 0;
}

bool AndroidControl::is_msg(const char *cp)
{
	if( msg_len != (int)strlen(cp) ) return false;
	if( strncmp(cp, msg, msg_len) ) return false;
	return true;
}

void AndroidControl::press(int key)
{
// printf("press 0x%04x\n",key);
	if( key == KPMENU && mwindow_gui->keyev_grab_remote() )
		printf("android grab remote\n");
	if( mwindow_gui->key_listener(key) ) return;
	mwindow_gui->remote_control->remote_key(key);
}

void AndroidControl::run()
{
	unsigned short port = mwindow_gui->mwindow->preferences->android_port;
	done = open(port) >= 0 ? 0 : 1;

	while( !done ) {
		struct sockaddr sadr;
		socklen_t sadr_len;
		enable_cancel();
		int ret = recvfrom(sockfd, buf, sizeof(buf), 0, &sadr, &sadr_len);
		if( ret < 0 ) {
			perror("AndroidControl::run: recvfrom");
			sleep(1);
		}
		disable_cancel();
		// validate message
		msg = buf;  msg_len = ret;
		// cinelerra android remote magic number
		if( msg[0] != 'C' || msg[1] != 'A' || msg[2] != 'R' ) continue;
		// version number
		if( msg[3] != 1 ) continue;
		msg += 4;  msg_len -= 4;
		// pin
		const char *pin = mwindow_gui->mwindow->preferences->android_pin;
		int len = sizeof(mwindow_gui->mwindow->preferences->android_pin);
		while( len > 0 && msg_len > 0 && *pin != 0 && *msg != 0 ) {
			if( *pin != *msg ) break;
			++pin;  --len;
			++msg;  --msg_len;
		}
		if( !len || !msg_len || *pin != *msg ) continue;
		++msg; --msg_len;
		if( msg_len <= 0 ) continue;
		if( is_msg("menu") ) press(KPMENU);
		else if( is_msg("key 0") ) press('0');
		else if( is_msg("key 1") ) press('1');
		else if( is_msg("key 2") ) press('2');
		else if( is_msg("key 3") ) press('3');
		else if( is_msg("key 4") ) press('4');
		else if( is_msg("key 5") ) press('5');
		else if( is_msg("key 6") ) press('6');
		else if( is_msg("key 7") ) press('7');
		else if( is_msg("key 8") ) press('8');
		else if( is_msg("key 9") ) press('9');
		else if( is_msg("key A") ) press('a');
		else if( is_msg("key B") ) press('b');
		else if( is_msg("key C") ) press('c');
		else if( is_msg("key D") ) press('d');
		else if( is_msg("key E") ) press('e');
		else if( is_msg("book") ) press(KPBOOK);
		else if( is_msg("rplay") ) press(KPREV);
		else if( is_msg("stop") ) press(KPSTOP);
		else if( is_msg("play") ) press(KPPLAY);
		else if( is_msg("media_lt") ) press(LEFT);
		else if( is_msg("media_rt") ) press(RIGHT);
		else if( is_msg("media_up") ) press(UP);
		else if( is_msg("media_dn") ) press(DOWN);
		else if( is_msg("pause") ) press(' ');
		else if( is_msg("slow_lt") ) press(KPRECD);
		else if( is_msg("slow_rt") ) press(KPAUSE);
       		else if( is_msg("fast_lt") ) press(KPBACK);
		else if( is_msg("fast_rt") ) press(KPFWRD);
		else if( is_msg("fscrn") ) press(KPFSCRN);
		else if( is_msg("mute") ) press(KPMUTE);
		else if( is_msg("vol_up") ) press(KPVOLUP);
		else if( is_msg("vol_dn") ) press(KPVOLDN);
		else if( is_msg("ch_up") ) press(KPCHUP);
		else if( is_msg("ch_dn") ) press(KPCHDN);
		else if( is_msg("key dot") ) press('.');
		else if( is_msg("key cc") ) press(KPCC);
		else if( is_msg("key tv") ) press(KPTV);
		else if( is_msg("hand") ) press(KPHAND);
		else if( is_msg("suspend") ) {
			system("sync; sleep 1; acpitool -s");
		}
		else if( is_msg("power") ) {
			system("sync; sleep 1; poweroff");
		}
		else {
			printf("AndroidControl::run: unkn msg: %s\n", msg);
			sleep(1);
		}
	}
}

AndroidControl::~AndroidControl()
{
	if( Thread::running() ) {
		done = 1;
		Thread::cancel();
	}
	Thread::join();
}

