# -*- coding: utf-8 -*-

import ppp
import utils
import runtime, config
from mms_net_socket import MMS_Socket
from mms_net_pdu import MMS_Http, M_Send_Req_PDU, M_NotifyResp_Ind_PDU, \
	M_Send_Conf, Get_CurrentDate, M_Acknowledge_Ind_PDU, M_Retrieve_Conf
from mmsmanager import MMSMessageInfo
from mms_net_define import *
from mmsconfig import *
from mmsmanager import mmsmgr
import socket

class MMS_Net_BaseCTR:
	def __init__(self, commobj=None):
		self.m_ppp = None
		self.m_socket = MMS_Socket(commobj)
		self.m_HTTPHeader = MMS_Http()
		self.job_tag = None
		self.ppp_max = None
		self.m_pppconnectiontimer = None

	def __del__(self):
		if self.m_pppconnectiontimer:
			runtime.evas.timeout_remove(self.m_pppconnectiontimer)
			self.m_pppconnectiontimer = None
		self.PPP_TimerRemove()

	def PPP_TimerRemove(self):
		if self.ppp_max:
			runtime.evas.timeout_remove(self.ppp_max)
			self.ppp_max = None

	def PPP_Close(self):
		from profile import profile
		if 0 == profile.get_profile() and None != self.m_ppp:
			try:
				self.m_ppp.stop_ppp()
				self.CTR_Fail()
			except:
				pass

	def PPP_Open(self, successcb, failcb):
		self.m_ppp = ppp.PPP(2)
		self.m_ppp.call_ppp(config.sac5, successcb, failcb)

	def Init_Network(self):
		from profile import profile
		if 0 == profile.get_profile():
			self.m_pppconnectiontimer = \
			runtime.evas.timeout_add(2000, self.Start_Transcation)
		else:
			self.job_tag = utils.Idle(self.job_cb)

	def job_cb(self):
		self.Start_Transcation()
		return False

	def Start_Transcation(self):
		if self.m_pppconnectiontimer:
			runtime.evas.timeout_remove(self.m_pppconnectiontimer)
			self.m_pppconnectiontimer = None

		from profile import profile
		if DEBUG_MMS_NET:
			print 'send.Start_Transaction', profile.get_profile()
		if 0 == profile.get_profile():
			self.ppp_max = runtime.evas.timeout_add(25000, self.PPP_MaxtimerCb)
			self.PPP_Open(self.PPP_ConnectCB, self.PPP_ConnectFailCB)
		else:
			self.PPP_ConnectCB()

	def PPP_MaxtimerCb(self):
		if (self.ppp_max):
			self.PPP_TimerRemove()
			self.PPP_Close()

class M_Send_CTR(MMS_Net_BaseCTR):
	def __init__(self, sendmsg=True, commobj=None):
		MMS_Net_BaseCTR.__init__(self, commobj)
		self.m_sendresult = False
		self.m_MSendReqPDU = M_Send_Req_PDU(mmsmgr.msg)
		self.m_MSendConf = M_Send_Conf()

		if False == sendmsg:
			self.Make_M_Send_Req(False)

		if DEBUG_MMS_NET:
			print 'mms_net_ctr.M_Send_CTR.init', sendmsg

	def Begin_MSend(self):
		return

	def CTR_Success(self):
		from mms_net_sendstage import MMS_Send_Stage
		mmssndstage = None
		if ('mmssendstage' == runtime.manager.stage.get_name()):
			mmssndstage = runtime.manager.stage
		else:
			mmssndstage = runtime.manager.find_stage('mmssendstage')

		if mmssndstage:
			mmssndstage.Success()

	def CTR_Fail(self):
		from mms_net_sendstage import MMS_Send_Stage
		mmssndstage = None
		if ('mmssendstage' == runtime.manager.stage.get_name()):
			mmssndstage = runtime.manager.stage
		else:
			mmssndstage = runtime.manager.find_stage('mmssendstage')

		if mmssndstage:
			mmssndstage.Fail()

	def PPP_ConnectFailCB(self):
		self.PPP_TimerRemove()
		self.CTR_Fail()

	def PPP_ConnectCB(self):
		self.PPP_TimerRemove()

		try:
			self.MSend_Transaction()
		except:
			self.CTR_Fail()
			return

		self.PPP_Close()

		try:
			if self.m_MSendConf.Get_Result():
				self.m_sendresult = True
				self.CTR_Success()
			else:
				self.CTR_Fail()
		except:
			self.CTR_Fail()

	def MSend_Transaction(self):
		self.m_socket.Connect(mmsmgr.mmsurl, mmsmgr.mmscport)
		self.Send_M_Send_Req()
		self.Recv_M_Send_Conf()
		self.m_socket.Disconnect()

	def Recv_M_Send_Conf(self):
		self.m_MSendConf.Recv_Response(self.m_socket)

		if TEST_CTR_NET:
			fd = open('messages/msendconf', 'wb+')
			fd.write(self.m_MSendConf.m_response_buffer)
			fd.close()

	def Send_M_Send_Req(self):
		totsendsize = self.m_MSendReqPDU.Get_PDU_Size() + \
			len(self.m_HTTPHeader.m_HTTPheader_buffer)
		if DEBUG_MMS_NET:
			print 'Send_M_Send_Req', totsendsize
		self.m_socket.Init_SendTotSize()
		self.m_HTTPHeader.Send_HTTPHeader(self.m_socket, totsendsize)
		self.m_MSendReqPDU.Send_M_Send_Req_PDU(self.m_socket, totsendsize)
		if TEST_CTR_NET:
			self.m_socket.Send_Data('\r\n\r\n')
		if DEBUG_MMS_NET:
			print 'mms_net_ctr.M_Send_CTR.Send_M_Send_Req END'

	def Make_M_Send_Req(self, sendmsg=True):
		if DEBUG_MMS_NET:
			print 'Make_M_Send_Req'
		self.m_MSendReqPDU.Make_M_Send_Req_PDU()
		if (sendmsg):
			pdusize = self.m_MSendReqPDU.Get_PDU_Size()
			if TEST_CTR_NET:
				pdusize += 4
			if DEBUG_MMS_NET:
				print 'pdusize', pdusize
			self.m_HTTPHeader.Make_HTTP_POST(pdusize, mmsc_url=mmsmgr.mmsurl)

	def Save_Message(self, box_path=None):
		if DEBUG_MMS_NET:
			print 'mms_net_ctr.M_Send_CTR.Save_Message'

		if None == box_path:
			filepath = mms_temp_message + Get_CurrentDate()
		else:
			msgsize = self.m_MSendReqPDU.Get_PDU_Size() / 1024
			if not utils.check_free_storage('mms_save', msgsize):
				if DEBUG_MMS_NET:
					print 'Save_Message.starage FULL', box_path
				from basemodel import StorageFullError
				raise StorageFullError
				return
			filepath = box_path + Get_CurrentDate()

		if DEBUG_MMS_NET:
			print filepath

		self.m_MSendReqPDU.Save_MMS_PDU(filepath)
		return filepath

class M_Retrieve_CTR(MMS_Net_BaseCTR):
	def __init__(self, commobj=None):
		MMS_Net_BaseCTR.__init__(self, commobj)
		if DEBUG_MMS_NET:
			print 'M_Retrieve_CTR'
		self.m_noti_info = None
		self.m_success = False
		self.job_tag = None

		self.m_MNotifyRespIndPDU = None
		self.m_AcknowledgeIndPDU = None
		self.m_RetrieveConf = None

	def Set_MRetrieve(self, noti_info):
		if DEBUG_MMS_NET:
			print 'M_Retrieve_CTR.Set_MRetrieve'
			print noti_info
			print '7:', noti_info[7]
		self.m_noti_info = noti_info
		self.m_MNotifyRespIndPDU = M_NotifyResp_Ind_PDU()
		self.m_AcknowledgeIndPDU = M_Acknowledge_Ind_PDU(self.m_noti_info[7])
		self.m_RetrieveConf = M_Retrieve_Conf()

	def Get_NewInfo(self):
		self.m_noti_info[5] = self.m_RetrieveConf.Get_MRetrieveConf_Info()
		return self.m_noti_info

	def Begin_MRetrieve(self, noti_info):
		return
		self.Set_MRetrieve(noti_info)
		self.Make_MNotifyRespInd()
		self.Init_Network()

	def Save_Message(self):
		fname = mms_message_inbox + Get_CurrentDate()
		self.m_RetrieveConf.Save_Retrieve_Message(fname)
		return fname

	def Make_AcknowledgeInd(self):
		if self.m_RetrieveConf.m_mmsheader_field.m_XMmsTrancationId:
			self.m_AcknowledgeIndPDU.Make_M_Acknowledge_Ind_PDU(self.m_RetrieveConf.m_mmsheader_field.m_XMmsTrancationId.data)
		else:
			self.m_AcknowledgeIndPDU.Make_M_Acknowledge_Ind_PDU(self.m_RetrieveConf.m_mmsheader_field.m_XMmsTrancationId)

		self.m_HTTPHeader.Make_HTTP_POST(self.m_AcknowledgeIndPDU.Get_PDU_Size(),
			'Connection: Close\r\n', mmsmgr.mmsurl)

	def Make_MNotifyRespInd(self):
		self.m_MNotifyRespIndPDU.Make_M_NotifyResp_Ind_PDU(self.m_noti_info[7])
		if DEBUG_MMS_NET:
			print 'M_Retrieve_CTR::Make_MNotifyRespInd url', self.m_noti_info[6]
		self.m_HTTPHeader.Make_HTTP_POST(self.m_MNotifyRespIndPDU.Get_PDU_Size(),
			'Connection: Keep-Alive\r\n', mmsc_url=mmsmgr.mmsurl)

	def Make_GETReq(self):
		self.m_HTTPHeader.Make_HTTP_GET(self.m_noti_info[6])
		if DEBUG_MMS_NET:
			print 'Make_GETReq'
			print self.m_HTTPHeader.m_HTTPheader_buffer

	def Send_AcknowledgeInd(self):
		self.m_HTTPHeader.Send_HTTPHeader(self.m_socket)
		self.m_AcknowledgeIndPDU.Send_M_Acknowledge_Ind_PDU(self.m_socket)

	def Send_GETReq(self):
		if DEBUG_MMS_NET:
			print 'Send_GETReq'
		self.m_HTTPHeader.Send_HTTPHeader(self.m_socket)

	def Send_MNotifyRespInd(self):
		self.m_HTTPHeader.Send_HTTPHeader(self.m_socket)
		self.m_MNotifyRespIndPDU.Send_M_NotifyResp_Ind_PDU(self.m_socket)

	def CTR_Success(self):
		runtime.manager.stage.Exit_Stage()

	def CTR_Fail(self):
		runtime.manager.stage.Exit_Stage()

	def PPP_ConnectFailCB(self):
		self.PPP_TimerRemove()
		self.CTR_Fail()

	def MRete_Transaction(self):
		tempname = ''
		try:
			if TEST_CTR_NET and TEST_LG_NAS:
				self.m_socket.Connect(self.m_noti_info[6], testup=False)
			else:
				self.m_socket.Connect(self.m_noti_info[6])
		except:
			if TEST_CTR_NET:
				print 'MRete_Transaction.Connect except'
			return NMGR_MNETFAIL, tempname

		try:
			self.Send_MNotifyRespInd()
			self.m_RetrieveConf.Recv_Response(self.m_socket)
		except:
			if TEST_CTR_NET:
				print 'MRete_Transaction.SendMNotify except'
			return NMGR_MNETFAIL, tempname

		if (HTTP_OK != self.m_RetrieveConf.Get_NotifyRespInd_Result()):
			if TEST_CTR_NET:
				print 'MRete_Transaction.RecvNotifyresp Resultfail'
			self.m_socket.Disconnect()
			return NMGR_MMSRESULTFAIL, tempname

		try:
			self.Make_GETReq()

			self.Send_GETReq()
		except:
			if TEST_CTR_NET:
				print 'MRete_Transaction.GET except'
			return NMGR_MNETFAIL, tempname

		self.m_RetrieveConf.Recv_Response(self.m_socket, None, True)
		confresult = self.m_RetrieveConf.Get_MRetrieveConf_Result()
		if False == confresult[0]:
			if DEBUG_MMS_NET:
				print 'RetrieveConf fail'
				utils.make_dir('MMS_MSG/')
				fname = 'MMS_MSG/' + Get_CurrentDate()+'retresultfail'
				errorfile = open(fname, 'wb+')
				errorfile.write(self.m_RetrieveConf.m_response_buffer)
				errorfile.close()

			self.m_socket.Disconnect()
			if PARSING_FAIL == confresult[1]:
				return NMGR_MMSRESULTFAIL|NMGR_INCORRECT, tempname
			else:
				return NMGR_MMSRESULTFAIL, tempname

		try:
			msgsize = self.m_RetrieveConf.Get_RetrieveMsg_Size() / 1024
			if DEBUG_MMS_NET:
				print 'MRete_Transaction.RetrieveMsg_Size', msgsize
			if not utils.check_free_storage('mms_save', msgsize):
				if DEBUG_MMS_NET:
					print 'MRete_Transaction.starage FULL'
				from basemodel import StorageFullError
				raise StorageFullError
			else:
				tempname = self.Save_Message()
		except:
			if DEBUG_MMS_NET:
				print 'RetrieveConf fail'
			self.m_socket.Disconnect()
			return NMGR_SAVEFAIL, tempname

		try:
			self.Make_AcknowledgeInd()
			self.Send_AcknowledgeInd()
		except:
			if TEST_CTR_NET:
				print 'MRete_Transaction.Acknow except'
			return NMGR_MNETFAIL, tempname

		self.m_socket.Disconnect()
		self.m_success = True
		return NMGR_NOERROR, tempname


	def PPP_ConnectCB(self):
		self.PPP_TimerRemove()

		self.m_socket.Connect(self.m_noti_info[6])

		self.Send_MNotifyRespInd()

		self.m_RetrieveConf.Recv_Response()
		if (HTTP_OK != self.m_RetrieveConf.Get_NotifyRespInd_Result()):
			self.m_socket.Disconnect()
			self.PPP_Close()
			self.CTR_Fail()
			return

		self.Make_GETReq()

		self.Send_GETReq()


		self.m_RetrieveConf.Recv_Response()
		if (False == self.m_RetrieveConf.Get_MRetrieveConf_Result()):
			if DEBUG_MMS_NET:
				print 'RetrieveConf fail'
			self.m_socket.Disconnect()
			self.PPP_Close()
			self.CTR_Fail()
			return
		try:
			self.Save_Message()
		except:
			if DEBUG_MMS_NET:
				print 'RetrieveConf failexcept'
			self.m_socket.Disconnect()
			self.PPP_Close()
			from mms_net_stage import MMSFullStage
			runtime.manager.change_stage(MMSFullStage())
			return

		self.Make_AcknowledgeInd()
		self.Send_AcknowledgeInd()

		self.m_socket.Disconnect()
		self.m_success = True

		self.PPP_Close()

		self.CTR_Success()

class M_Forward_CTR(MMS_Net_BaseCTR):
	def __init__(self, forwardinfo):
		MMS_Net_BaseCTR.__init__(self)
		self.m_mforwardreq = M_Forward_Req(forwardinfo)
		self.m_mworwardconf = M_Forward_Conf()
		self.m_success = False

	def Begin_MForward(self):
		self.Make_MForwardReq()
		self.Init_Network()

	def Make_MForwardReq(self):
		self.m_mforwardreq.Make_M_Forward_Req_PDU()
		self.m_HTTPHeader.Make_HTTP_POST(self.m_mforwardreq.Get_PDU_Size())

	def Send_MForwardReq(self):
		self.m_HTTPHeader.Send_HTTPHeader(self.m_socket)
		self.m_mforwardreq.Send_M_Forward_Req_PDU(self.m_socket)

	def CTR_Success(self):
		pass
	def CTR_Fail(self):
		pass

	def PPP_ConnectFailCB(self):
		self.CTR_Fail()
		pass

	def PPP_ConnectCB(self):
		self.PPP_TimerRemove()
		self.m_socket.Connect('')
		self.Send_MForwardReq()
		self.m_mworwardconf.Recv_Response()

		self.m_socket.Disconnect()
		self.PPP_Close()

		if (False == self.m_mworwardconf.Get_MForwardConf_Result()):
			if DEBUG_MMS_NET:
				print 'MForwardConf fail'
		else:
			self.m_success = True

class Net_Comm:
	def __init__(self):
		pass

	def Start_Comm(self):
		self.m_client_s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
		self.m_client_s.connect(NMGR_SOCK_FILE)

	def Recv_Packet(self):
		c = self.m_client_s.recv(1)
		packetlen = ord(c)
		msg = ''
		while packetlen > 0:
			m = self.m_client_s.recv(1)
			packetlen -= len(m)
			msg += m

		if DEBUG_MMS_NET:
			print 'clt:', ord(c), ',',  ord(msg[0]), ',', msg[1:]

		return msg

	def Send_Packet(self, buf):
		import struct
		p = struct.pack('B', len(buf))
		self.m_client_s.send(p)
		self.m_client_s.send(buf)
		if DEBUG_MMS_NET:
			print 'clt.Send_Packet -->', p, ',', buf

def MRetreive_Client():
	errortype = NMGR_NOERROR
	savedname = ''
	netcomm = Net_Comm()
	netcomm.Start_Comm()
	mretreivectr = M_Retrieve_CTR(netcomm)
	netcomm.Send_Packet(chr(NMGR_CONNECT))
	while 1:
		receive = netcomm.Recv_Packet()

		if NMGR_MCTRBEGIN & ord(receive[0]):

			tokens = receive[1:].split(',', 8)
			if len(tokens) != 9:
				pass
			filename, t, isread, address, report, subject, \
				url, transactionid, mmsexpiry = tokens
			info = [filename, t, int(isread), address, int(report),\
				subject, url, transactionid, mmsexpiry]

			mretreivectr.Set_MRetrieve(info)
			mretreivectr.Make_MNotifyRespInd()

			errortype, savedname = mretreivectr.MRete_Transaction()

			info = mretreivectr.Get_NewInfo()
			fname, t, isread, address, report, subject, url, transactionid, \
				mmsexpiry = info
			newinfo = '%s,%s,%d,%s,%d,%s,%s,%s,%s' % \
			(fname, t, isread, address, report, subject, url, transactionid, mmsexpiry)
			if DEBUG_MMS_NET:
				print 'retreive new info'
				print newinfo
			netcomm.Send_Packet(chr(NMGR_MRETREIVECOMP)+newinfo)

			netcomm.Send_Packet(chr(errortype)+savedname)

def MSend_Client():
	errortype = NMGR_NOERROR
	savedname = ''
	netcomm = Net_Comm()
	netcomm.Start_Comm()
	msendctr = M_Send_CTR(True, netcomm)
	netcomm.Send_Packet(chr(NMGR_CONNECT))

	while 1:
		receive = netcomm.Recv_Packet()

		if NMGR_MCTRBEGIN & ord(receive[0]):
			try:
				msendctr.Make_M_Send_Req()
				msendctr.MSend_Transaction()
			except:
				errortype |= NMGR_MNETFAIL

			try:
				savedname = msendctr.Save_Message()
			except:
				errortype |= NMGR_SAVEFAIL

			if (NMGR_MNETFAIL & errortype):
				netcomm.Send_Packet(chr(errortype)+savedname)
				continue

			if msendctr.m_MSendConf.Get_Result():
				msendctr.m_sendresult = True
				netcomm.Send_Packet(chr(errortype)+savedname)
			else:
				if DEBUG_MMS_NET:
					print 'MSend_Client.Get_Result Fail'
					utils.make_dir('MMS_MSG/')
					fname = 'MMS_MSG/' + Get_CurrentDate()+'sendresultfail'
					errorfile = open(fname, 'wb+')
					errorfile.write(msendctr.m_MSendConf.m_response_buffer)
					errorfile.close()
				errortype |= NMGR_MMSRESULTFAIL
				netcomm.Send_Packet(chr(errortype)+savedname)
