#!/usr/bin/python

import os
import shutil
import threading
import re
import time
from time import sleep
from selenium import webdriver, common
# ^ If not installed just run:
# sudo easy_install selenium


WAITTIME = 1.8 #kindof hacky, adjustable
PWD = file('pwapp').read().strip()
VERSION = '1.0.11'
SIKULI  = '/Applications/SikuliX.app/run -r FILE'

class AppDeveloperInterface:
	def __init__(self, browser):
		""" Start a appdeveloper site session given selenium webdriver """
		self.browser = browser
		self.browser.get('http://developer.apple.com/account/ios/')
		elementuser = browser.find_elements_by_id('accountname')[0]
		elementpass = browser.find_elements_by_id('accountpassword')[0]
		elementuser.send_keys('appdev@sharefaith.com')
		elementpass.send_keys(PWD+'\n')
		
	def createAppID(self, name, bundleID):
		name = name.replace("\n", "")
		bundleID = bundleID.replace("\n", "")
		if not bundleID.startswith('com.sharefaith'):
			raise Exception('bad bundleid')
		if name.startswith('com.sharefaith'):
			raise Exception('bad name')
			
		#self.browser.get('https://developer.apple.com/account/ios/certificate/certificateList.action')
		#self.browser.get('https://developer.apple.com/account/ios/identifiers/bundle/bundleList.action')
		self.browser.get('https://developer.apple.com/account/ios/identifiers/bundle/bundleCreate.action')
		simplename = name
		#This doesn't work with comma, - etc.:
		simplename = re.sub('[^0-9a-zA-Z]+',' ', simplename).strip()
		if len(simplename) == 0:
			raise Exception('bad name')
		sleep(0.5)
		self.q('.text-input.appIdName.validate').send_keys(simplename)
		
		#Set explicit id, bundleid
		self.q('.radio-wrapper.explicit input.radio').click()
		self.q('.radio-wrapper.explicit input.appIdentifierString').send_keys(bundleID)
		self.q('input[type=checkbox][name=push]').click()
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		
	def createPushCert(self, name, bundleID):
		name = name.replace("\n", "")
		bundleID = bundleID.replace("\n", "")
		if not bundleID.startswith('com.sharefaith'):
			raise Exception('bad bundleid')
		if name.startswith('com.sharefaith'):
			raise Exception('bad name')
			
		self.browser.get('https://developer.apple.com/account/ios/certificate/certificateCreate.action')
		self.q('input#type-production').click()
		sleep(WAITTIME) #Careful, without this it seems it'll name it the previous app's name?
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.selectorSelect(bundleID)
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		#TODO finish automate keychain?
		#file(os.path.expanduser('~/Desktop/CreateSigReq.sikuli/commonname.txt'), 'w').write(name)
		if 0 != os.system(SIKULI.replace('FILE', '~/Desktop/CreateSigReq.sikuli --args "'+name+'"')):
			raise Exception('createsig fail.')
		#TODO test. certSigningrequest of this one is in desktop now:
		os.system("mv ~/Desktop/CertificateSigningRequest.certSigningRequest ../CertificateSigningRequest.certSigningRequest");
		self.q(".formContent .file-input.validate").send_keys(os.path.realpath("../CertificateSigningRequest.certSigningRequest"))
		
		#Now go download:
		#sleep(WAITTIME)
		#self.q('[href^="/account/ios/certificate/certificateContentDownload.action"]').click()
		
	def createProvisioningProfile(self, name, bundleID):
		name = name.replace("\n", "")
		bundleID = bundleID.replace("\n", "")
		if not bundleID.startswith('com.sharefaith'):
			raise Exception('bad bundleid')
		if name.startswith('com.sharefaith'):
			raise Exception('bad name')
			
		self.browser.get('https://developer.apple.com/account/ios/profile/profileCreate.action')
		self.q('.form input#type-production').click()
		
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.selectorSelect(bundleID)
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('input[value="[PQ3PAD54VV]"]').click() #The current Dec 01 cert.
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('input[name="provisioningProfileName"]').send_keys(bundleID)
		sleep(WAITTIME)
		#unspecified error, need wait? self.q('.submit[role=button]').click()
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		try: #kinda odd "An unspecified error" box - works anyway
			self.q('.ui-dialog-content.ui-widget-content .bottom-buttons >.ok.button').click()
			sleep(0.3)
			self.q('.submit[role=button]').click()
			sleep(WAITTIME)
		except:
			print'no err box'
		#Download:
		self.q('[href^="/account/ios/profile/profileContentDownload.action"]').click()
		sleep(WAITTIME)
		if (0 != os.system('open ../'+bundleID.replace('.','')+'.mobileprovision' ) ):
			print 'NO PROVISION file???'
		
	def createAdHocProvisioningProfile(self, name, bundleID):
		name = name.replace("\n", "")
		bundleID = bundleID.replace("\n", "")
		if not bundleID.startswith('com.sharefaith'):
			raise Exception('bad bundleid')
		if name.startswith('com.sharefaith'):
			raise Exception('bad name')
			
		self.browser.get('https://developer.apple.com/account/ios/profile/profileCreate.action')
		self.q('.form input#type-adhoc').click()
		
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.selectorSelect(bundleID)
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('input[value="[PQ3PAD54VV]"]').click() #The current Dec 01 cert.
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('.form .header .selectAll input').click() #Select all devices for adhoc - unlike production mode
		sleep(WAITTIME)
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		self.q('input[name="provisioningProfileName"]').send_keys('Ad-Hoc '+bundleID)

		sleep(WAITTIME)
		#unspecified error, need wait? self.q('.submit[role=button]').click()
		self.q('.submit[role=button]').click()
		sleep(WAITTIME)
		try: #kinda odd "An unspecified error" box - works anyway
			self.q('.ui-dialog-content.ui-widget-content .bottom-buttons >.ok.button').click()
			sleep(0.3)
			self.q('.submit[role=button]').click()
			sleep(WAITTIME)
		except:
			print'no err box'
		#Download:
		self.q('[href^="/account/ios/profile/profileContentDownload.action"]').click()
		sleep(WAITTIME)
		if (0 != os.system('open ../AdHoc_'+bundleID.replace('.','')+'.mobileprovision' ) ):
			print 'NO PROVISION file???'
		
	def selectorSelect(self, bundleID):
		""" Selects the current app from dropdown select element """
		found = False
		appselector = self.q('select[name=appIdId]')
		for element in appselector.find_elements_by_tag_name('option'):
			appid = element.text.strip().strip(")")
			#formid = element.get_attribute('value')
			if appid.endswith(bundleID):
				element.click()
				#print appid, formid
				found = True
		if not found:
			raise Exception('No selection for appid '+bundleID)
		
	def q(self, selector):
		""" basically like querySelector() """
		return self.browser.find_element_by_css_selector(selector)


class iTunesConnectInterface:
	def __init__(self, browser):
		self.browser = browser
		self.browser.get('http://itunesconnect.apple.com/')
		elementuser = browser.find_elements_by_id('accountname')[0]
		elementpass = browser.find_elements_by_id('accountpassword')[0]
		elementuser.send_keys('appdev@sharefaith.com')
		elementpass.send_keys(PWD+'\n')
		
		try:
			self.q('.sign-out-modal .modal-dialog-content [href="/WebObjects/iTunesConnect.woa"]')
			self.browser.get('http://itunesconnect.apple.com/')
			elementuser = browser.find_elements_by_id('accountname')[0]
			elementpass = browser.find_elements_by_id('accountpassword')[0]
			elementuser.send_keys('appdev@sharefaith.com')
			elementpass.send_keys(PWD+'\n')
		except:
			pass #ok, no log-back-in-msg
		
	def createNewApp(self, name, bundleID, description, keywords):
		name = name.replace("\n", "")
		bundleID = bundleID.replace("\n", "")
		if not bundleID.startswith('com.sharefaith'):
			raise Exception('bad bundleid')
		if name.startswith('com.sharefaith'):
			raise Exception('bad name')
		
		#self.browser.get("https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/958640856")
		#sleep(5)
		#self.fillIn(name, bundleID, description, keywords)
		#return;
			
		self.browser.get('https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app')
		#Wait for all ajax stuff to load
		sleep(5)
		self.q('.left-side .new-button').click()
		self.q("""[bo-bind="l10n.interpolate('ITC.apps.manageyourapps.summary.newiosapp')"] """).click()
		sleep(WAITTIME) #dialog should pop up. fill in:
		self.q('input[ng-model="createAppDetails.newApp.name.value"]').send_keys(name)
		self.q('input[ng-model="createAppDetails.newApp.vendorId.value"]').send_keys(bundleID)
		sel = self.q('select[ng-model="createAppDetails.newApp.primaryLanguage.value"] option[value="6"]')
		if sel.text == 'English':
			sel.click()
		else:
			raise Exception('What, no English?')
		
		self.q('select[ng-model="createAppDetails.newApp.bundleId.value"] option[value="'+bundleID+'"]').click()
		self.q('input[ng-model="createAppDetails.versionString.value"]').send_keys(VERSION)
		sleep(WAITTIME) #now create new:
		self.q('button.primary[ng-click="saveApp()"]').click()
		
		self.waitFor('[ng-show="versionInfo.details.value[currentLoc].description.isEditable"] textarea') #Once page is loaded, fill in details:
		self.fillIn(name, bundleID, description, keywords)
		
	def fillIn(self, name, bundleID, description, keywords):
		try:
			self.q('[ng-show="versionInfo.details.value[currentLoc].description.isEditable"] textarea').send_keys(description)
			self.q('[ng-show="versionInfo.details.value[currentLoc].keywords.isEditable"] >input').send_keys(keywords)
		except UnicodeDecodeError, e: #Caused by funny quotes?
			print "ERROR inputting desc/keyword you'll need to enter these manually\n"
			
		self.q('[ng-show="versionInfo.details.value[currentLoc].supportURL.isEditable"] >input').send_keys('http://www.sharefaith.com/category/church-websites.html')
		self.q('[ng-show="versionInfo.copyright.isEditable"] >input[type=text]').send_keys('Sharefaith')
		self.q('[ng-show="versionInfo.appReviewInfo.firstName.isEditable"] >input[type=text]').send_keys('Chris')
		self.q('[ng-show="versionInfo.appReviewInfo.lastName.isEditable"] >input[type=text]').send_keys('Ostmo')
		self.q('[ng-show="versionInfo.appReviewInfo.phoneNumber.isEditable"] >input[type=text]').send_keys('888-317-4018')
		self.q('input[ng-required="versionInfo.appReviewInfo.emailAddress.isRequired"]').send_keys('appdev@sharefaith.com')
		
		selcategory = self.q('[ng-model="versionInfo.primaryCategory.value"] option[value="9"]')
		if selcategory.text.strip() == 'Lifestyle':
			selcategory.click()
		else:
			raise Exception('What, no lifestyle app category?')
		
		#Select all the correct ratings:
		self.q('a[ng-show="versionInfo.ratings.isEditable"]').click()
		for element in self.browser.find_elements_by_css_selector('[radio-value="ITC.apps.ratings.level.NONE"] a'):
			element.click()
		for element in self.browser.find_elements_by_css_selector('[radio-value="ITC.apps.ratings.level.NO"] a'):
			element.click()
		#Close rating dialog:
		self.q('[ng-click="closeRatingModal(true)"]').click()
		
		#Uploaders - sending full path to file should upload it
		for i in [6,5,4,3,2,1,0]: #Reverse order
			relpath = 'images/phonescreen-'+str(i)+'.png'
			self.uploadIfExists(relpath)
		
		if (self.waitforUploaded()):
			self.q('.pilltabgroup li[role=menuitem][value=ipad]').click()
			for i in [6,5,4,3,2,1,0]: #Reverse order
				relpath = 'images/tabletscreen-'+str(i)+'.png'
				self.uploadIfExists(relpath)
			
			if (self.waitforUploaded()):
				self.q('.pilltabgroup li[role=menuitem][value=iphone4]').click()
				for i in [6,5,4,3,2,1,0]: #Reverse order
					relpath = 'images/phonescreen4-'+str(i)+'.png'
					self.uploadIfExists(relpath)
				
				if (self.waitforUploaded()):
					self.q('.pilltabgroup li[role=menuitem][value=iphone35]').click()
					self.uploadIfExists('images/launch-640x960.png')
					if (self.waitforUploaded()):
						#Upload logo
						#It's hidden
						self.browser.execute_script(""" jQuery('[ng-show="versionInfo.largeAppIcon.isEditable"] [type=file]').css('left','0') """)
						self.q('[ng-show="versionInfo.largeAppIcon.isEditable"] [type=file]').send_keys(os.path.realpath('images/storeicon-1024x1024.png'))
						sleep(WAITTIME)
						self.q('[itc-radio="versionInfo.releaseOnApproval.value"][radio-value="false"] a').click()
						
						self.q('[ng-click="saveVersionDetails()"]').click()
		
	def uploadIfExists(self, relpath):
		if os.path.isfile(relpath): #Send the full path to send_keys to upload:
			tosend = os.path.realpath(relpath)
			#print 'sending', tosend
			self.q('input#mainDropTrayFileSelect').send_keys(tosend)
			sleep(0.4)

	
	def waitforUploaded(self):
		#Wait up to 4 min?
		for i in range(60*8):
			try:
				self.q('.pilltabgroup.disabled')
				sleep(0.5) # wait til enabled again.
			except common.exceptions.NoSuchElementException, e:
				return True #Disabled was not found, switcher's ready again.
		return False #Not found yet?
		
	def waitFor(self, selector):
		#Wait up to 4 min?
		for i in range(60*8):
			try:
				self.q(selector)
				#No exception! exists
				return True
			except common.exceptions.NoSuchElementException, e:
				sleep(0.4)
		#Not found still?
		raise Exception('Not found '+selector)
		
	#TODO checking existence, could integrate new-app and update-app eventually. Moved to Java for possible performance benefit with Jython-sikuli-IDE?
	def findApp(id):
		self.browser.get('https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app')
		self.waitFor('li.app')
		self.q('input.search-input').send_keys(id+'\n')
		#print len(browser.find_elements_by_css_selector('#searchTextResults li.app'))
		sleep(3)
		found = len(self.browser.find_elements_by_css_selector('#searchTextResults li.app'))
		if (found == 1):
			self.q('#searchTextResults li.app .app-icon a').click()
			self.waitFor(browser, 'textarea')
		else:
			pass #new one here...
		
		
	def q(self, selector):
		""" basically like querySelector() """
		return self.browser.find_element_by_css_selector(selector)

def buildXcode():
	os.system('open ../Sharefaith\ ChurchApp/ios/Sharefaith\ ChurchApp.xcodeproj')
	sleep(2)
	if 0 != os.system(SIKULI.replace('FILE', '~/Desktop/xcodeauto.sikuli')):
		raise Exception('Xcode-automate failed')
	if 0 != os.system("mv ~/Desktop/Sharefaith\ ChurchApp.ipa ../Sharefaith\ ChurchApp.ipa"):
		raise Exception('Xcode-automate move to folder failed')
		
	dsymdir = os.path.expanduser(time.strftime("~/Library/Developer/Xcode/Archives/%Y-%m-%d/")) #today's dir
	latest = 0
	latestname = ""
	for arch in os.listdir(dsymdir):
		if os.path.getmtime(dsymdir+arch) > latest and arch != ".DS_Store":
			latest = os.path.getmtime(dsymdir+arch)
			latestname = arch
	print latestname,'copying...'
	print dsymdir
	print latestname
	shutil.copy(os.path.join(dsymdir, latestname, "/dSYMs/Sharefaith ChurchApp.app.dSYM"), "../Sharefaith ChurchApp.app.dSYM")
	print "copied"
		
# End class defs, interactive code below:
try:
	tocwd = raw_input('working dir? ')
	os.chdir(tocwd)
	contentslist = os.listdir('.')
	for item in contentslist:
		if os.path.isdir(item) and \
		  (not item == '__MACOSX') and \
		  (not item.endswith('.dSYM')) and \
		  (not item == 'Sharefaith ChurchApp'):
			datadirectory = item
	#datadirectory is '83g2598gakfdisahf98' or something
	print 'dir:', datadirectory, 'this will be a v'+VERSION
	os.chdir(datadirectory)
	description = file('description.txt').read()
	keywords   = file('keywords.txt').read()
	titleAndId = file('title_and_id.txt').readlines()

	if len(titleAndId) == 2:
		title = titleAndId[0].strip()
		bundleID = titleAndId[1].strip() #no newlines end!
		print 'OK, that is:'
		print title
		print 'which is ID:'
		print bundleID

		autoDL = webdriver.FirefoxProfile()
		autoDL.set_preference("browser.download.manager.showWhenStarting", False)
		autoDL.set_preference("browser.download.dir", os.path.dirname(os.getcwd()) )
		autoDL.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream")
		autoDL.set_preference("browser.download.folderList", 2)

		browserWindow = webdriver.Firefox( firefox_profile=autoDL )
		browser = AppDeveloperInterface( browserWindow )
		while True:
			print '1:Create appid'
			print '2:Start create pushcert'
			print '3:Generate,install app Production Provisioning Profile'
			print '4:Generate,install app Adhoc Provisioning Profile'
			print '5:Start iTunesConnect'
			print '6:Xcode build'
			action = raw_input('Enter Action  #')
			if action == '1':
				browser.createAppID(title, bundleID)
			if action == '2':
				browser.createPushCert(title, bundleID)
			if action == '3':
				browser.createProvisioningProfile(title, bundleID)
			if action == '4':
				browser.createAdHocProvisioningProfile(title, bundleID)
			if action == '5':
				itconnect = iTunesConnectInterface(browserWindow)
				itconnect.createNewApp(title, bundleID, description, keywords)
			if action == '6':
				buildXcode()
			if action == '5,6':
				thread = threading.Thread(target=buildXcode, args=())
				thread.daemon = True
				thread.start()
				itconnect = iTunesConnectInterface(browserWindow)
				itconnect.createNewApp(title, bundleID, description, keywords)
		
			#while (1): #allow some testing
			#	try:
			#		print eval(raw_input(''))
			#	except Exception, e:
			#		print 'Exception -',e
	else:
		raise Exception('Invalid Title/ID file')
except KeyboardInterrupt, e:
	print ' '
	if raw_input('Exit? This will close the browser.  y/n ') == 'y':
		exit()