#!/usr/bin/python

from xml.dom import minidom
import httplib
import urllib
import re

# Receiver internet connection info
global IP_ADDRESS
global PORT
IP_ADDRESS = "192.168.0.0"
PORT = "80"
#print IP_ADDRESS

# EventGhost Constnats
ACTION_EXECBUILTIN = 0x01
ACTION_BUTTON = 0x02

# Yamaha request xml constants
BASIC_STATUS_XML = '<YAMAHA_AV cmd="GET"><Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone></YAMAHA_AV>'
Z2_BASIC_STATUS_XML = '<YAMAHA_AV cmd="GET"><Zone_2><Basic_Status>GetParam</Basic_Status></Zone_2></YAMAHA_AV>'
TUNER_STATUS_XML = '<YAMAHA_AV cmd="GET"><Tuner><Play_Info>GetParam</Play_Info></Tuner></YAMAHA_AV>'
TUNER_PRESETS_XML = '<YAMAHA_AV cmd="GET"><Tuner><Play_Control><Preset><Data>GetParam</Data></Preset></Play_Control></Tuner></YAMAHA_AV>'
CONFIG_XML = '<YAMAHA_AV cmd="GET"><System><Config>GetParam</Config></System></YAMAHA_AV>'
PC_STATUS_XML = '<YAMAHA_AV cmd="GET"><PC><Play_Info>GetParam</Play_Info></PC></YAMAHA_AV>'
PC_PLAY_XML = '<YAMAHA_AV cmd="PUT"><PC><Play_Control><Playback>GetParam</Playback></Play_Control></PC></YAMAHA_AV>'
IR_CODE_XML = '<YAMAHA_AV cmd="PUT"><System><Misc><Remote_Signal><Receive><Code>GetParam</Code></Receive></Remote_Signal></Misc></System></YAMAHA_AV>'
SYSTEM_NET_XML = '<YAMAHA_AV cmd="GET"><System><Misc><Network><UPnP_Friendly_Name>GetParam</UPnP_Friendly_Name></Network></Misc></System></YAMAHA_AV>'

def get_xml(XML):
	conn = httplib.HTTPConnection("%s:%s" % ( IP_ADDRESS, PORT ))
	headers = { "Content-type": "text/xml" }
	conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers)
	conn.send(XML)
	response = conn.getresponse()
	rval = response.read()
	conn.close()
	#print "this is the response from rx-v"
	return rval

def get_basic_status(zone = 0):
	if zone == 0:
		return get_xml(BASIC_STATUS_XML)
	elif zone == 2:
		return get_xml(Z2_BASIC_STATUS_XML)
	else:
		print "beyond zone 2 not implemented"

def get_PC_status():
	return get_xml(PC_STATUS_XML)

def get_net_status():
	return get_xml(SYSTEM_NET_XML)

def get_tuner_status():
	return get_xml(TUNER_STATUS_XML)

def get_tuner_presets():
	return get_xml(TUNER_PRESETS_XML)

def get_config():
	return get_xml(CONFIG_XML)

def send_xml(XML):
	conn = httplib.HTTPConnection("%s:%s" % ( IP_ADDRESS, PORT ))
	headers = { "Content-type": "text/xml" }
	conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers)
	conn.send(XML)
	conn.close()

def change_volume(diff = 0, zone = 0):
	print diff
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>%i</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>' % int(get_volume() + 10 * diff))
	elif zone == 2:
		print "im here"
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Volume><Lvl><Val>%i</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Zone_2></YAMAHA_AV>' % int(get_volume(2) + 10 * diff))
	else:
		print "More than 2 zones not yet supported"

def get_volume(zone = 0):
	return get_int_param('Val', zone)
    
def set_volume(value, zone = 0):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>%i</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>' % int(value * 10.0))
	elif zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Volume><Lvl><Val>%i</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></Zone_2></YAMAHA_AV>' % int(value * 10.0))
	else:
		print "more than 2 zones not yet supported"

def mute_on(zone):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Mute>On</Mute></Volume></Main_Zone></YAMAHA_AV>')
	elif zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Volume><Mute>On</Mute></Volume></Zone_2></YAMAHA_AV>')
	else:
		print "not implemented"

def mute_off(zone):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Mute>Off</Mute></Volume></Main_Zone></YAMAHA_AV>')
	elif zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Volume><Mute>Off</Mute></Volume></Zone_2></YAMAHA_AV>')
	else:
		print "not implemented"

def get_mute(zone):
	return get_is_param_on('Mute', zone)

def power_on(zone =0):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>On</Power></Power_Control></Main_Zone></YAMAHA_AV>')
	if zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Power_Control><Power>On</Power></Power_Control></Zone_2></YAMAHA_AV>')

def power_off(zone =0):
	print zone
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>')
	if zone == 2:
		print "got in"
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Power_Control><Power>Standby</Power></Power_Control></Zone_2></YAMAHA_AV>')

def power_standby():
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>')

def toggle_on_standby():
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>On/Standby</Power></Power_Control></Main_Zone></YAMAHA_AV>')    

def toggle_mute(zone = 0):
	if get_mute(zone):
		mute_off(zone)
	else:
		mute_on(zone)

def change_source(source, zone = 0):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Input><Input_Sel>%s</Input_Sel></Input></Main_Zone></YAMAHA_AV>' % source)
	elif zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT"><Zone_2><Input><Input_Sel>%s</Input_Sel></Input></Zone_2></YAMAHA_AV>' % source)
	else:
		print "zones beyond 2 not yet supported"

def straight():
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Surround><Program_Sel><Current><Straight>On</Straight><Sound_Program>Straight</Sound_Program></Current></Program_Sel></Surround></Main_Zone></YAMAHA_AV>')

def surround_decode():
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Surround><Program_Sel><Current><Straight>Off</Straight><Sound_Program>Surround Decoder</Sound_Program></Current></Program_Sel></Surround></Main_Zone></YAMAHA_AV>')

def toggle_straight_decode():
	if get_straight():
		surround_decode()
	else:
		straight()

def get_straight():
	return get_is_param_on('Straight')

def set_enhancer(arg):
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Surround><Program_Sel><Current><Enhancer>%s</Enhancer></Current></Program_Sel></Surround></Main_Zone></YAMAHA_AV>' % arg)

def get_enhancer():
	return get_is_param_on('Enhancer')

def get_sound_program_name():
	return get_string_param('Sound_Program')
    
def get_source_number():
	return get_int_param('Src_Number')

def get_is_param_on(param, zone = 0):
	return get_string_param(param, zone) == "On"

def get_int_param(param, zone = 0):
	return int(get_string_param(param, zone))
    
def get_string_param(param, zone = 0):
	xml = get_basic_status(zone)
	xmldoc = minidom.parseString(xml)
	return xmldoc.getElementsByTagName(param)[0].firstChild.data

def get_string_param_PC(param):
	xml = get_PC_status()
	xmldoc = minidom.parseString(xml)
	return xmldoc.getElementsByTagName(param)[0].firstChild.data


def get_string_param_net(param):
	xml = get_PC_status()
	xmldoc = minidom.parseString(xml)
	return xmldoc.getElementsByTagName(param)[0].firstChild.data

def get_string_param_tuner(param):
	xml = get_tuner_status()
	xmldoc = minidom.parseString(xml)
	return  xmldoc.getElementsByTagName(param)[0].firstChild.data

def get_is_tuner_param_on(param):
	return get_string_param_tuner(param) == "On"    

def get_int_tuner_param(param):
	return int(get_string_param_tuner(param))    

def toggle_enhancer():
	if get_enhancer():
		set_enhancer("Off")
	else:
		set_enhancer("On")

def next_source(zone = 0):
	set_source_number(get_source_number(zone) + 1)

def previous_source(zone = 0):
	set_source_number(get_source_number(zone) - 1)

def set_source_number(num, zone = 0):
	if zone == 0:
		send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Input><Current_Input_Sel_Item><Src_Number>%i</Src_Number></Current_Input_Sel_Item></Input></Main_Zone></YAMAHA_AV>' % num)
	elif zone == 2:
		send_xml('<YAMAHA_AV cmd="PUT">Zone_2><Input><Current_Input_Sel_Item><Src_Number>%i</Src_Number></Current_Input_Sel_Item></Input></Zone_2></YAMAHA_AV>' % num)
	else:
		print "not implemented"
	
def set_sleep(arg):
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Sleep>On</Sleep></Power_Control></Main_Zone></YAMAHA_AV>')  
    
def toggle_sleep():
	if (get_is_param_on('Sleep')):
		set_sleep('Off')
	else:
		set_sleep('On')

def set_radio_preset(preset):
	send_xml('<YAMAHA_AV cmd="PUT"><Tuner><Play_Control><Preset><Preset_Sel>%i</Preset_Sel></Preset></Play_Control></Tuner></YAMAHA_AV>' % preset)

def get_radio_band():
	return get_string_param_tuner('Band')

def toggle_radio_amfm():
	if get_radio_band() == 'FM':
		set_radio_band('AM')
	else:
		set_radio_band('FM')
    
def set_radio_band(band):
	send_xml('<YAMAHA_AV cmd="PUT"><Tuner><Play_Control><Tuning><Band>%s</Band></Tuning></Play_Control></Tuner></YAMAHA_AV>' % band)
            
def modify_radio_preset(diff, turn_on, wrap):
	oldpreset = get_int_tuner_param('Preset_Sel')
	preset = oldpreset + diff
	set_radio_preset(preset)
	if turn_on:
		is_on = is_radio_on
		if not is_on:
			change_source('TUNER')
	if wrap and (not turn_on or is_on):
		count = get_radio_preset_count()
		if diff > 0 and preset > count:
			preset = 1
			set_radio_preset(preset)
		elif diff < 0 and preset < 1:
			preset = count
			set_radio_preset(preset)
        
def is_radio_on():
	return get_string_param('Input_Sel') == "TUNER"
        
def auto_radio_freq(updown):
	send_xml('<YAMAHA_AV cmd="PUT"><Tuner><Play_Control><Auto_Freq>%s</Auto_Freq></Play_Control></Tuner></YAMAHA_AV>' % updown)

def manual_radio_freq(updown):
	send_xml('<YAMAHA_AV cmd="PUT"><Tuner><Play_Control><Tuning><Freq>%s</Freq></Tuning></Play_Control></Tuner></YAMAHA_AV>' % updown)    
    
def set_radio_freq(freq):
	#could be used to send in whole radio frequency and band
	print "Not implemented!"

def get_radio_preset_count():
	xml = get_tuner_presets()
	xmldoc = minidom.parseString(xml)
	count = 0
	done = False
	while not done and count <= 40:
		num = "Number_%s" % (count + 1)
		value = xmldoc.getElementsByTagName(num)[0].getElementsByTagName('Status')[0].firstChild.data
		if value == 'Exist':
			count = count + 1
		else:
			done = True
	return count

def set_scene(scene_num):
	send_xml('<YAMAHA_AV cmd="PUT"><Main_Zone><Scene><Scene_Sel>Scene %i</Scene_Sel></Scene></Main_Zone></YAMAHA_AV>' % scene_num)

def set_cursor(action, zone = 0):
	#print action
	if zone == 0:
		if action =='Up':
			code = '7A859D62'
		elif action =='Down':
			code = '7A859C63'
		elif action =='Left':
			code = '7A859F60'
		elif action =='Right':
			code = '7A859E61'
		elif action =='Enter':
			code = '7A85DE21'
		elif action =='Return':
			code = '7A85AA55'
		elif action =='Level':
			code = '7A858679'
		elif action =='On_Screen':
			code = '7A85847B'
		elif action =='Option':
			code = '7A856B14'
		elif action =='Top_Menu':
			code = '7A85A0DF'
		elif action =='Pop_Up_Menu':
			code = '7A85A4DB'
	if zone == 2:
		if action =='Up':
			code = '7A852B55'
		elif action =='Down':
			code = '7A852C52'
		elif action =='Left':
			code = '7A852D53'
		elif action =='Right':
			code = '7A852E50'
		elif action =='Enter':
			code = '7A852F51'
		elif action =='Return':
			code = '7A853C42'
		elif action =='Option':
			code = '7A856C12'
		elif action =='Top_Menu':
			code = '7A85A1DF'
		elif action =='Pop_Up_Menu':
			code = '7A85A5DB'
	#print code
	send_xml('<YAMAHA_AV cmd="PUT"><System><Misc><Remote_Signal><Receive><Code>%s</Code></Receive></Remote_Signal></Misc></System></YAMAHA_AV>' % code)
	
def set_numchar(action, zone = 0):
	#print action
	if zone == 0:
		if action =='1':
			code = '7F0151AE'
		elif action =='2':
			code = '7F0152AD'
		elif action =='3':
			code = '7F0153AC'
		elif action =='4':
			code = '7F0154AB'
		elif action =='5':
			code = '7F0155AA'
		elif action =='6':
			code = '7F0156A9'
		elif action =='7':
			code = '7F0157A8'
		elif action =='8':
			code = '7F0158A7'
		elif action =='9':
			code = '7F0159A6'
		elif action =='0':
			code = '7F015AA5'
		elif action =='+10':
			code = '7F015BA4'
		elif action =='ENT':
			code = '7F015CA3'
	if zone == 2:
		if action =='1':
			code = '7F01718F'
		elif action =='2':
			code = '7F01728C'
		elif action =='3':
			code = '7F01738D'
		elif action =='4':
			code = '7F01748A'
		elif action =='5':
			code = '7F01758B'
		elif action =='6':
			code = '7F017688'
		elif action =='7':
			code = '7F017789'
		elif action =='8':
			code = '7F017886'
		elif action =='9':
			code = '7F017986'
		elif action =='0':
			code = '7F017A84'
		elif action =='+10':
			code = '7F017B85'
		elif action =='ENT':
			code = '7F017C82'
	print code
	print zone
	send_xml('<YAMAHA_AV cmd="PUT"><System><Misc><Remote_Signal><Receive><Code>%s</Code></Receive></Remote_Signal></Misc></System></YAMAHA_AV>' % code)

def set_operation(action, zone = 0):
	if zone == 0:
		if action =='Play':
			code = '7F016897'
		elif action =='Stop':
			code = '7F016996'
		elif action =='Pause':
			code = '7F016798'
		elif action =='Search-':
			code = '7F016A95'
		elif action =='Search+':
			code = '7F016E94'
		elif action =='Skip-':
			code = '7F016C93'
		elif action =='Skip+':
			code = '7F016D92'
		elif action =='FM':
			code = '7F015827'
		elif action =='AM':
			code = '7F01552A'
	if zone == 2:
		if action =='Play':
			code = '7F018876'
		elif action =='Stop':
			code = '7F018977'
		elif action =='Pause':
			code = '7F018779'
		elif action =='Search-':
			code = '7F018A74'
		elif action =='Search+':
			code = '7F018B75'
		elif action =='Skip-':
			code = '7F018C72'
		elif action =='Skip+':
			code = '7F018D73'
		elif action =='FM':
			code = '7F015927'
		elif action =='AM':
			code = '7F015628'
	send_xml('<YAMAHA_AV cmd="PUT"><System><Misc><Remote_Signal><Receive><Code>%s</Code></Receive></Remote_Signal></Misc></System></YAMAHA_AV>' % code)

def main():
	print "MAIN"
    
if __name__ == "__main__":
    main()
    
class RXVClient:
	def __init__(self):
		print "Init"

	def send_action(self, msg = '', type = ACTION_EXECBUILTIN):
		if msg.startswith('VolumeUp_'):
			change_volume(float(msg.replace('VolumeUp_', '')))
		elif msg.startswith('VolumeDown_'):
			change_volume(float(msg.replace('VolumeDown_', ''))*(0-1))
		elif msg == 'ToggleMute':
			toggle_mute()
		elif msg == 'PowerOn':
			power_on()
		elif msg == 'PowerOff':
			power_off()
		elif msg == 'PowerStandby':
			power_standby()    
		elif msg == 'ToggleOnStandby':
			toggle_on_standby()  
		elif msg.startswith('Source_'):
			change_source(msg.replace('Source_', ''))
		elif msg == 'Straight':
			straight()
		elif msg == 'SurroundDecode':
			surround_decode()
		elif msg == 'ToggleStraightAndDecode':
			toggle_straight_decode()
		elif msg == 'ToggleEnhancer':
			toggle_enhancer()
		elif msg == 'PreviousSource':
			next_source()
		elif msg == 'NextSource':
			Previous_source()
		elif msg == 'ToggleRadioAMFM':
			toggle_radio_amfm()
		elif msg == 'RadioAutoFeqUp':
			auto_radio_freq('Up')
		elif msg == 'RadioAutoFreqDown':
			auto_radio_freq('Down')
		elif msg == 'RadioFeqUp':
			manual_radio_freq('Up')
		elif msg == 'RadioFreqDown':
			manual_radio_freq('Down')
		elif msg == 'ToggleSleep':
			toggle_sleep()
		elif msg == 'NextRadioPreset':
			modify_radio_preset(1, True, True)
		elif msg == 'PreviousRadioPreset':
			modify_radio_preset(-1, True, True)
		elif msg.startswith('Scene'):
			set_scene(int(msg.replace('Scene', '')))
		#does stop,play,pause,search-hold,search+tag,skip-,skip+,FM,AM
		elif msg.startswith('Operation_'):
			set_operation(msg.replace('Operation_', ''))
		#does 1,2,3,4,5,6,7,8,9,+10,ENT
		elif msg.startswith('NumChar_'):
			set_numchar(msg.replace('NumChar_', ''))
		#does on_screen,option,top_menu,pop_up_menu,up,down,left,right,enter,return,level
		elif msg.startswith('Cursor_'):
			set_cursor(msg.replace('Cursor_', ''))



	def get_action(self, msg = '', type = ACTION_EXECBUILTIN):
		msg = msg.replace('Get_','')
		if msg.startswith('Basic_'):
			eg.globals.YamahaReturn = get_string_param(msg.replace('Basic_', ''))
			return eg.globals.YamahaReturn
		elif msg.startswith('Tuner_'):
			eg.globals.YamahaReturn = get_string_param_tuner(msg.replace('Tuner_', ''))
			return eg.globals.YamahaReturn
		elif msg.startswith('PC_'):
			eg.globals.YamahaReturn = get_string_param_PC(msg.replace('PC_', ''))
			return eg.globals.YamahaReturn
		print "Problem with action, there is no match"

	def send_z2_action(self, msg = '', type = ACTION_EXECBUILTIN):
		zone = 2
		if msg.startswith('VolumeUp_'):
			change_volume(float(msg.replace('VolumeUp_', '')),zone)
		elif msg.startswith('VolumeDown_'):
			change_volume(float(msg.replace('VolumeDown_', ''))*(0-1),zone)
		elif msg == 'ToggleMute':
			toggle_mute(zone)
		elif msg == 'PowerOn':
			power_on(zone)
		elif msg == 'PowerOff':
			power_off(zone)
		elif msg.startswith('Source_'):
			change_source(msg.replace('Source_', ''), zone)
		elif msg == 'PreviousSource':
			next_source(zone)
		elif msg == 'NextSource':
			Previous_source(zone)
		#does stop,play,pause,search-hold,search+tag,skip-,skip+,FM,AM
		elif msg.startswith('Operation_'):
			set_operation(msg.replace('Operation_', ''), zone)
		#does 1,2,3,4,5,6,7,8,9,+10,ENT
		elif msg.startswith('NumChar_'):
			set_numchar(msg.replace('NumChar_', ''), zone)
		#does on_screen,option,top_menu,pop_up_menu,up,down,left,right,enter,return,level
		elif msg.startswith('Cursor_'):
			set_cursor(msg.replace('Cursor_', ''), zone)

	def get_z2_action(self, msg = '', type = ACTION_EXECBUILTIN):
		msg = msg.replace('Get_','')
		zone = 2
		print "switched and still in Z2"
		print msg
		if msg.startswith('Basic_', zone):
			eg.globals.YamahaReturn = get_string_param(msg.replace('Basic_', ''), zone)
			return eg.globals.YamahaReturn
		elif msg.startswith('Tuner_'):
			eg.globals.YamahaReturn = get_string_param_tuner(msg.replace('Tuner_', ''))
			return eg.globals.YamahaReturn
		elif msg.startswith('PC_'):
			eg.globals.YamahaReturn = get_string_param_PC(msg.replace('PC_', ''))
			return eg.globals.YamahaReturn
		print "Problem with action, there is no match"