class Node:
	def __init__(self, payLoad, next=None):
		self.payLoad = payLoad
		self.next = next

	def __str__(self):
		return str(self.payLoad)

	def __repr__(self):
		return self.__str__()

class LinkedList:
	def __init__(self, item):
		self.next = self.next = self.__check_Node(item)
		self.head = self.next

	def __repr__(self):
		return self.__str__()
  
	def __add__(self, item):
		'''allow += and + operates to work correctly'''
		if item is self: return False
		self.push( item )

		return self

	def __iter__(self):
		'''allow the in operator to work'''
		current = self.next

		while isinstance(current, Node):
			yield current
			current = current.next

	def __len__(self):
		'''allow the len() function to be used'''
		return self.find( None )['count']

	def __str__(self):
		'''allow print to work correctly'''
		current = self.next
		out = 'Head' + ' => '

		for current in self:
		# while current:
			out += str(current.payLoad) + ' => '
			current = current.next

		return out + 'None'

	def __check_Node(self, node):
		'''internal method check if node is a node object'''
		if isinstance(node, self.__class__):
			return node.head

		if not isinstance(node, Node):
			return Node(node)

		return node

	def find(self, match):
		''' Searches the list for a matching node. If found it will return the
			current node, last node as Node objects and position as an int.
			If nothing is found, it will return None, the last node as a Node
			object, and the full length of the list as an int.

			This function will **ONLY** return the first match.

			setting match to None will find the end of the list and return the
			last node as return['last']

			This method does alot of the heavy lifting.
		'''

		current = self.next
		last = None
		count = 0

		while current:
			if current.payLoad == match:
				return {'current': current, 'last': last, 'count': count}

			last = current
			current = current.next
			count += 1

		return {'current': current, 'last': last, 'count': count}

	def insert(self, *items, after=False):

		# figures out the position of the node
		previous_node = self.find(after)['current'] if after != False else self

		for item in items[:: -1]:

			if isinstance(item, self.__class__):
				item = item.next

			item = self.__check_Node( item )
			item.next = previous_node.next
			previous_node.next = item

		return self

	def push(self, item):
		last_node = self.find(None)['last']
		node = self.__check_Node(item)
		last_node.next = node;


	def print_right(self):

		def rec(current):
			if not current: return 'None'
			return rec( current.next ) + ' <= ' + current.payLoad

		return rec( self.next ) + ' <= Head' 

	def delete(self, payLoad):
		match = self.find( payLoad )
		if match['current']:
			match['last'].next = match['current'].next
			return match['current'];

		return None

if __name__ == '__main__':
	''' Some testing stuff '''
	l1 = LinkedList('b')
	l1.insert('a')
	l1.push('c')

	print(l1)

	l2 = LinkedList('1')
	l2.push('2')

	print(l2)

	l1 +=l2
	print(l1)

