/*
 * Copyright (C) 2015 Intel Corp
 *
 * 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 <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <linux/input.h>
#include <cutils/log.h>
#include "InputEventReader.h"



struct input_event;

InputEventCircularReader::InputEventCircularReader(size_t numEvents)
			: mBuffer(new input_event[numEvents * 2]),
			mBufferEnd(mBuffer + numEvents),
			mHead(mBuffer),
			mCurr(mBuffer),
			mFreeSpace(numEvents)
{
	FUNC_LOG;
	mLastFd = -1;
}

InputEventCircularReader::~InputEventCircularReader()
{
	FUNC_LOG;
	delete [] mBuffer;
}

/* TODO: clear DEBUG flag on production builds, keep it during integration */
#define INPUT_EVENT_DEBUG (0)
ssize_t InputEventCircularReader::fill(int fd)
{
	FUNC_LOG;
	size_t numEventsRead = 0;
	mLastFd = fd;

	LOGV_IF(INPUT_EVENT_DEBUG,
			"DEBUG:%s enter, fd=%d\n", __PRETTY_FUNCTION__, fd);
	if (mFreeSpace) {
		const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
		if (nread < 0 || nread % sizeof(input_event)) {
			/* LOGE("Partial event received nread=%d, required=%d",
			     nread, sizeof(input_event));
			LOGE("FD trying to read is: %d"); */
			/* we got a partial event!! */
			if (INPUT_EVENT_DEBUG) {
				LOGV_IF(nread < 0, "DEBUG:%s exit nread < 0\n",
							__PRETTY_FUNCTION__);
				LOGV_IF(nread % sizeof(input_event),
							"DEBUG:%s exit nread %% sizeof(input_event)\n",
							__PRETTY_FUNCTION__);
			}
			return (nread < 0 ? -errno : -EINVAL);
		}

		numEventsRead = nread / sizeof(input_event);
		if (numEventsRead) {
			mHead += numEventsRead;
			mFreeSpace -= numEventsRead;
			if (mHead > mBufferEnd) {
				size_t s = mHead - mBufferEnd;
				memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
				mHead = mBuffer + s;
			}
		}
	}

	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s exit, numEventsRead:%d\n",
			__PRETTY_FUNCTION__, numEventsRead);
	return numEventsRead;
}

ssize_t InputEventCircularReader::readEvent(input_event const** events)
{
	FUNC_LOG;
	*events = mCurr;
	ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, available:%d\n",
			__PRETTY_FUNCTION__, mLastFd, (int)available);
	return (available ? 1 : 0);
}

void InputEventCircularReader::next()
{
	FUNC_LOG;
	mCurr++;
	mFreeSpace++;
	if (mCurr >= mBufferEnd)
		mCurr = mBuffer;

	ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
	LOGV_IF(INPUT_EVENT_DEBUG, "DEBUG:%s fd:%d, still available:%d\n",
				__PRETTY_FUNCTION__, mLastFd, (int)available);
}

