# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import array
import errno
import logging
import os

from portage.util import writemsg_level
from _emerge.AsynchronousTask import AsynchronousTask

class AbstractPollTask(AsynchronousTask):

	__slots__ = ("scheduler",) + \
		("_registered",)

	_bufsize = 4096

	@property
	def _exceptional_events(self):
		return self.scheduler.IO_ERR | self.scheduler.IO_NVAL

	@property
	def _registered_events(self):
		return self.scheduler.IO_IN | self.scheduler.IO_HUP | \
			self._exceptional_events

	def isAlive(self):
		return bool(self._registered)

	def _read_array(self, f, event):
		"""
		NOTE: array.fromfile() is used here only for testing purposes,
		because it has bugs in all known versions of Python (including
		Python 2.7 and Python 3.2). See PipeReaderArrayTestCase.

		| POLLIN | RETURN
		| BIT    | VALUE
		| ---------------------------------------------------
		| 1      | Read self._bufsize into an instance of
		|        | array.array('B') and return it, handling
		|        | EOFError and IOError. An empty array
		|        | indicates EOF.
		| ---------------------------------------------------
		| 0      | None
		"""
		buf = None
		if event & self.scheduler.IO_IN:
			buf = array.array('B')
			try:
				buf.fromfile(f, self._bufsize)
			except EOFError:
				pass
			except TypeError:
				# Python 3.2:
				# TypeError: read() didn't return bytes
				pass
			except IOError as e:
				# EIO happens with pty on Linux after the
				# slave end of the pty has been closed.
				if e.errno == errno.EIO:
					# EOF: return empty string of bytes
					pass
				elif e.errno == errno.EAGAIN:
					# EAGAIN: return None
					buf = None
				else:
					raise

		if buf is not None:
			try:
				# Python >=3.2
				buf = buf.tobytes()
			except AttributeError:
				buf = buf.tostring()

		return buf

	def _read_buf(self, fd, event):
		"""
		Read self._bufsize into a string of bytes, handling EAGAIN and
		EIO. This will only call os.read() once, so the caller should
		call this method in a loop until either None or an empty string
		of bytes is returned. An empty string of bytes indicates EOF.
		None indicates EAGAIN.

		NOTE: os.read() will be called regardless of the event flags,
			since otherwise data may be lost (see bug #531724).

		@param fd: file descriptor (non-blocking mode required)
		@type fd: int
		@param event: poll event flags
		@type event: int
		@rtype: bytes or None
		@return: A string of bytes, or None
		"""
		# NOTE: array.fromfile() is no longer used here because it has
		# bugs in all known versions of Python (including Python 2.7
		# and Python 3.2).
		buf = None
		try:
			buf = os.read(fd, self._bufsize)
		except OSError as e:
			# EIO happens with pty on Linux after the
			# slave end of the pty has been closed.
			if e.errno == errno.EIO:
				# EOF: return empty string of bytes
				buf = b''
			elif e.errno == errno.EAGAIN:
				# EAGAIN: return None
				buf = None
			else:
				raise

		return buf

	def _unregister(self):
		raise NotImplementedError(self)

	def _log_poll_exception(self, event):
		writemsg_level(
			"!!! %s received strange poll event: %s\n" % \
			(self.__class__.__name__, event,),
			level=logging.ERROR, noiselevel=-1)

	def _unregister_if_appropriate(self, event):
		if self._registered:
			if event & self._exceptional_events:
				self._log_poll_exception(event)
				self._unregister()
				self.cancel()
				self.wait()
			elif event & self.scheduler.IO_HUP:
				self._unregister()
				self.wait()

	def _wait(self):
		if self.returncode is not None:
			return self.returncode
		self._wait_loop()
		return self.returncode

	def _wait_loop(self, timeout=None):

		if timeout is None:
			while self._registered:
				self.scheduler.iteration()
			return

		def timeout_cb():
			timeout_cb.timed_out = True
			return False
		timeout_cb.timed_out = False
		timeout_cb.timeout_id = self.scheduler.timeout_add(timeout, timeout_cb)

		try:
			while self._registered and not timeout_cb.timed_out:
				self.scheduler.iteration()
		finally:
			self.scheduler.source_remove(timeout_cb.timeout_id)
