#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

#@PydevCodeAnalysisIgnore

import sys

from win32pipe import *
from win32file import *
from win32event import *
import win32api
import winerror

# Our imports
from winswitch.util.simple_logger import Logger
from winswitch.util.common import visible_command, no_newlines
from winswitch.net.local_common import PIPE_NAME
from winswitch.net.local_common import RESPONSE_OK, RESPONSE_NACK, COMMAND_PING
from winswitch.net.local_common import CLIENT_SUCCESS, CLIENT_ERROR_CONNECTION_FAILED, CLIENT_ERROR_NACK, CLIENT_ERROR_UNKNOWN_RESPONSE, CLIENT_UNKNOWN_ERROR

class LocalNamedPipeClient:
	def __init__(self, standalone=True):
		Logger(self, log_colour=Logger.YELLOW)
		self.messages = None
		self.exit_code = None
		self.sdebug(None, standalone)
		self.timedout = False
		self.testing = False

	def test_socket(self, message=COMMAND_PING):
		self.debug()
		try:
			self.testing = True
			code = self.send([message])
		finally:
			self.testing = False
		self.sdebug("exit code from send to named pipe '%s': %s" % (PIPE_NAME, code), message)
		return code == CLIENT_SUCCESS

	def send(self, msgs):
		self.exit_code = None
		self.messages = msgs
		self.slog(None, msgs)
		self.send_first_message()
		return self.exit_code


	def CallPipe(self, fn, args):
		retryCount = 0
		while not self.timedout and retryCount < 8:   # Keep looping until user cancels.
			self.sdebug("retryCount=%s" % retryCount, fn, args)
			retryCount = retryCount + 1
			try:
				return apply(fn, args)
			except win32api.error, e:
				#(rc, fnerr, msg) = e
				(rc, _, _) = e
				if rc==winerror.ERROR_PIPE_BUSY:
					self.serror("Pipe is busy, waiting", fn, args)
					win32api.Sleep(5000)
					continue
				else:
					raise e
		raise RuntimeError, "Could not make a connection to the server"

	def send_first_message(self):
		if len(self.messages)==0:
			self.sdebug("no more messages!")
			return
		msg = self.messages.pop()
		self.sdebug("sending '%s'" % msg)

		try:
			data = self.CallPipe(CallNamedPipe, (PIPE_NAME, msg, 256, NMPWAIT_WAIT_FOREVER))
			self.lineReceived(data)
		except win32api.error , exc:
			ERROR_PIPE_ENDED = 109
			ERROR_FILE_NOT_FOUND = 2
			error_code = exc[0]
			if error_code in [ERROR_FILE_NOT_FOUND, ERROR_PIPE_ENDED]:
				if self.testing:
					self.slog("connection failed/not found: %s " % exc)
				else:
					self.serror("connection failed/not found: %s " % exc)
				self.exit_code = CLIENT_ERROR_CONNECTION_FAILED
			else:
				self.serr("unknown error", exc)
				self.exit_code = CLIENT_UNKNOWN_ERROR


	def lineReceived(self, line):
		self.sdebug(None, visible_command(line))
		response = no_newlines(line)
		if response == RESPONSE_OK:
			if not self.exit_code:
				self.exit_code = CLIENT_SUCCESS
			self.send_first_message()
			return
		elif response == RESPONSE_NACK:
			self.exit_code = CLIENT_ERROR_NACK
		else:
			self.exit_code = CLIENT_ERROR_UNKNOWN_RESPONSE


def send_message(msg):
	return send_messages([msg])

def send_messages(msgs):
	client = LocalNamedPipeClient()
	return client.send(msgs)

def get_responses(msgs):
	client = LocalNamedPipeClient()
	if client.send(msgs)==CLIENT_SUCCESS:
		return	client.responses
	return None


if __name__ == '__main__':
	from winswitch.util.simple_logger import set_log_to_file, set_log_to_tty
	set_log_to_file(False)
	set_log_to_tty(True)
	exit_code = send_messages(sys.argv[1:])
	if exit_code:
		sys.exit(exit_code)
