import smtplib, os
import traceback
from email.message import EmailMessage
from random import randrange
from webdriver_manager.firefox import GeckoDriverManager
from selenium import webdriver
from selenium.webdriver.support.ui import Select
import selenium
from utillc import *
import cherrypy
import schedule, pycron
import datetime

def p_date() :
	now = datetime.datetime.now()
	#EKOX(now.strftime("%Y-%m-%d %H:%M:%S"))


EKOX(selenium.__version__)
usechrome = True

if usechrome :
	from selenium.webdriver.chrome.service import Service
	from selenium.webdriver.chrome.options import Options as  Options
	from selenium.webdriver import Chrome as Driver
	#import chromedriver_autoinstaller 
	#chromedriver_autoinstaller.install() 
else :
	from selenium.webdriver.firefox.service import Service
	from selenium.webdriver.firefox.options import Options as Options
	from selenium.webdriver import	Firefox as Driver


import PIL
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException

import time
import numpy as np

#wd = browser = webdriver.Firefox(executable_path=	  GeckoDriverManager().install())
EKO()
import sys
import time

import PIL
from PIL import Image


# https://www.zenrows.com/blog/selenium-avoid-bot-detection
# https://piprogramming.org/articles/How-to-make-Selenium-undetectable-and-stealth--7-Ways-to-hide-your-Bot-Automation-from-Detection-0000000017.html

#WebElement m = driver.findElement (By.xpath ("//*[contains(text(),'Get started ')]"));

debugging = True #False

no_christine = "0685848778"
no_secretariat = "0973017826"

# Initializing a list with two Useragents 
useragentarray = [ 
	"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", 
	"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", 
]

def toXPathStringLiteral(s):
    if "'" not in s: return "'%s'" % s
    if '"' not in s: return '"%s"' % s
    return "concat('%s')" % s.replace("'", "',\"'\",'")


class RobotBase :

		
	def __init__(self) :
		pass

	def get_parent(self, e) :
			return e.find_element(By.XPATH, '..')

	def get_parent_containing_tag(self, e, tag) :
		while True :
			ii = e.find_elements(By.TAG_NAME, tag)
			if len(ii) > 0 : return ii
			e = self.get_parent(e)
		return None

	def get_element_image(self, e) :
		x, y = e.location['x'], e.location['y']
		EKON(x, y)
		w, h = e.size['width'], e.size['height']
		EKON(w, h)
		im = self.screen()
		ee = im[y:y+h, x:x+w]
		EKOI(ee)
		return ee

	def find_txt(self, txt, num=0, exact=False) :
		EKOX(txt)
		escaped = toXPathStringLiteral(txt)
		ppth = "//*[contains(text(), %s)]" % escaped if not exact else  "//*[text() =  %s]" % escaped
		EKOX(ppth)

		try :
			btns = self.driver.find_elements(By.XPATH, ppth)
			EKOX(len(btns))
			EKOX(btns)
			for e in btns : self.get_element_image(e)
						
		except Exception as e :
				EKOX(e)
		EKO()
		self.wait.until(EC.presence_of_element_located((By.XPATH,ppth)))
		#self.wait.until(EC.element_to_be_clickable((By.XPATH,ppth)))
		EKOI(self.screen(), sz=800)
		EKOT("//*[contains(text(), %s)]" % escaped)
		btns = self.driver.find_elements(By.XPATH, ppth)
		EKON(num, len(btns))
		return btns[num]

	def check_txt_visible(self, txt) :
		escaped = toXPathStringLiteral(txt)
		el = self.wait.until(EC.presence_of_element_located((By.XPATH,"//*[contains(text(), %s)]" % escaped)))
		assert(el is not None)
	
	def do_click_txt(self, txt, num=0, exact=False) :
		EKOX(txt)
		btn = self.find_txt(txt, num=num, exact=exact)
		EKOX(btn)
		btn.click()


	def build(self, headless=True) :
		options = Options()
		EKO()
		options.add_argument('--no-sandbox')
		options.add_argument('--disable-dev-shm-usage')
		# changing user-agent because etoro detects the automated browser somehow
		options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) "
							 "Chrome/86.0.4240.183 Safari/537.36")
		EKO()

		if usechrome :
			#s = Service('/usr/bin/chromedriver')
			s = Service('./chromedriver_patched')
			if headless :
				options.add_argument('--headless=new')
			options.binary_location = "./chrome-linux64/chrome"
			options.add_argument("--disable-blink-features=AutomationControlled") 
			# Exclude the collection of enable-automation switches 
			options.add_experimental_option("excludeSwitches", ["enable-automation"]) 
			
			# Turn-off userAutomationExtension 
			options.add_experimental_option("useAutomationExtension", False) 
			options.add_argument("window-size=1280,800")
			options.add_argument('--disable-blink-features=AutomationControlled')

			self.driver = Driver(service=s, options=options)

			# Changing the property of the navigator value for webdriver to undefined 
			self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

			i = randrange(len(useragentarray))
			self.driver.execute_cdp_cmd("Network.setUserAgentOverride", {"userAgent": useragentarray[i]})
			EKO()
			
		else :
			self.driver = Driver(options=options)			 
		#self.driver = webdriver.Chrome('/usr/lib/chromium-browser/chromedriver', options=options)
		#self.driver = webdriver.Firefox(options=options)
		#self.driver.get("https://pythonbasics.org")
		#wd = webdriver.Firefox(service=service, options=options)
		EKO()
		pass
		self.wait = WebDriverWait(self.driver, 10)
		

	def screen(self) :
		if debugging :
			p = '/tmp/screenie.png'
			self.driver.save_screenshot(p)
			x = Image.open(p)
			#im = cv2.imread(p)
			im = np.array(x)		
			return im
		else :
			return np.zeros((3,3,3)).astype(np.uint8)

	def enter(self, x, txt, waitms=12000) :
		#EKON(x, txt)
		for i in range(50) :
			#EKOX(i)
			#EKOI(self.screen(), sz=800)			
			try :
				#self.driver.implicitly_wait(waitms/1000)				 
				elem = self.driver.find_element(By.XPATH, x)
				#EKOX(elem)
				assert(elem is not None)
				elem.send_keys(txt)
				#EKOX(elem.text)
				#EKOX(elem.get_attribute("value"))
				#EKOI(self.screen(), sz=800)
				#EKON(txt, elem.get_attribute("value"))
				if elem.get_attribute("value") == txt :
					#EKOT("######################## text %s entered in %s " % (txt, x))
					break
			except Exception as e:
				pass
			time.sleep(0.2)
		#EKOI(self.screen(), sz=800) 
		#EKOX(elem is not None and	elem.get_attribute("value") == txt)
		EKOX(elem.get_attribute("value"))
		#EKO()
		return x
	
	def found(self, x) :
		try :
			elem = self.driver.find_element(By.XPATH, x)
			return elem
		except Exception as e  :
			return None


	def select(self, x, value, waitms=0, mode=By.XPATH) :
		try :
			self.driver.implicitly_wait(waitms/1000)
			#EKO()
			s = Select(self.driver.find_element(mode, x))
			#EKO()
		except Exception as e  :
			EKOX(e)
			pass
		s.select_by_value(value)
		
		
	def click(self, x, absentOK=False, waitms=0, mode=By.XPATH) :
		#EKOX(x)
		try :
			self.driver.implicitly_wait(waitms/1000)
			elem = self.driver.find_element(mode, x)
					
		except Exception as e  :
			elem = None
			#EKON(absentOK)
			assert(absentOK)
			pass
		
		if elem is None :
			#EKOT("%s pas trouvé " % x)
			assert(absentOK)
			#EKOT("OK")
			return str(x) + " pas trouvé mais ok"
		else :
			assert(elem is not None)
			#EKOX(elem.text)
			#EKOT("#################### clicking %s " % elem.text)
			try :
				elem.click()
				return str(x) + " clicked"
				
			except :
				return "raté"
				pass
			
			#EKOT("clicked")
		
	def waittextin(self, x, txt) :
		EKO()
		self.driver.implicitly_wait(5)
		EKO()
		elem = None
		for i in range(10) :
			EKOX(i)
			try :
				elem = self.driver.find_element(By.XPATH, x)
				EKOX(elem.txt)
				if elem.text == txt :
					break
				else :
					time.sleep(0.5)					   
			except Exception as e  :
				EKOX(e)
				elem = None
				time.sleep(0.5)
				EKO()
		assert(elem is not None)
		EKOI(self.screen(), sz=800)

	def wait_one(self, l, waitms=10000) :
		d, ws = 0.1, waitms/1000
		K = 1. / d / len(l)
		S = ws / K / len(l) / d
		#EKON(S, K, ws)
		for sec in range(int(S)) :
			#EKOX(sec)
			#EKOI(self.screen(), sz=800)
			for _ in range(int(K)) :
				for ie, e in enumerate(l) :
					if self.found(e) :
						#EKOX(e)
						return e
					time.sleep(d)
		return None


	def find(self, mode, target) :
		try :
			e = self.driver.find_element(mode, target)
		except :
			e = None
		return e


class Robot(RobotBase) :
	"""
	L,Ma, Me,J,V
	8h -> 12h15 : Sec
	12h15 -> 12h50 : Messagerie 3 sonnerie
	12h50 -> 14h20 : Sec
	14h20 -> 15h30 : Tel portable
	15h30 -> 19h30 : Messagerie 3 sonnerie
	19h30 -> Lendemain : Sec

	S 
	8h -> 13h : Messagerie
	13h -> Lundi : Sec

	Me
	8h -> 12h : Sec
	12h -> 19h : Mess
	19h -> Lendemain : Sec
	"""



		
	MESSAGERIE = "MESSAGERIE"
	MESSAGERIE_3 = "MESSAGERIE_3"
	def mail(self, txt) :
		# set your email and password
		# please use App Password
		email_address = "louis.chevallier@gmail.com"
		email_password = os.environ["app_password_for_gmail"]

		# create email
		msg = EmailMessage()
		msg['Subject'] = "secretariat telephonique"
		msg['From'] = "louis.chevallier@gmail.com"
		msg['To'] = "louis.chevallier@gmail.com"
		msg.set_content(txt)

		# send email
		with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
			e = smtp.login(email_address, email_password)
			EKOX(e)
			e = smtp.send_message(msg)
			EKOX(e)
		EKOT("sent")

	def __init__(self) :
		super().__init__()
		self.build(headless=True)		 
		url = "https://espaceclientpro.orange.fr"
		self.url = "https://dro.orange.fr/authentification?TARGET=https://dro.orange.fr/detrompeur/B2B%3FcodeContexte%3DOPUS"
		EKO()
		test_page = "http://localhost/www_hd1/robot_test/example.html"
		EKO()
		browser_test = self.driver.get(test_page)
		#EKOX( self.driver.page_source)		   
		#EKOX(self.driver.find_element(By.ID, "log").text)
		EKO()
		#self.mail("coucou")
		#1/0
		browser = self.driver.get(self.url)		   
		EKOX(self.driver.title)
		html_source = self.driver.page_source
		#with open("html.html", "w") as fd : fd.write(html_source)

		EKOX(hash(html_source))

		
	def login(self) :
		EKOT(" ############################# Logging in...")

		browser = self.driver.get(self.url)
		identif = "/html/body/main/div[3]/div/div/div[2]/div[2]/form/div[2]"
		identif = '//*[@id="username"]'
		user = 'cabinetmedicalmelesse@orange.fr'
		EKOI(self.screen(), sz=800)

		accepter = '//*[@id="didomi-notice-agree-button"]'
		self.click(accepter, absentOK=True)
		EKOI(self.screen(), sz=800)
		sidentifier = '//*[@id="btnSubmit"]'
		#self.waittextin(sidentifier, "S'identifier")
		we = self.wait_one([identif])
		EKOX(we)
		self.enter(identif, user)
		EKO()


		#time.sleep(5)
		EKOI(self.screen(), sz=800)	 

			
		resteridentifie = '//*[@id="btnSubmit"]'
		try :
			suivant = '//*[@id="submit-button"]'
			self.click(suivant)
			EKOI(self.screen(), sz=800)
			pwdinput ='//*[@id="password"]'
			time.sleep(2)

			self.find_txt("Saisissez votre mot de passe")
			
			fwo = self.wait_one([pwdinput, resteridentifie])
			EKOX(fwo)
			EKOI(self.screen(), sz=800)
			if self.found(pwdinput)	 :
				EKOT("######################### entrée mot de passe")
				mdp = 'Chenes2023*'
				self.enter(pwdinput, mdp)
				EKOI(self.screen(), sz=800)
				#time.sleep(5)				
				self.click(sidentifier)
				
				EKOI(self.screen(), sz=800)

				
				time.sleep(5)
				EKOI(self.screen(), sz=800)	 

				
				EKO()
			
			else : 
				EKO()
				self.click(resteridentifie)
		except Exception as e :
			assert(False)
		EKO()
		decouvrirplustard = '/html/body/div[4]/div/div[2]/div[2]/div[3]/div/div/div/a'
		ce = self.click(decouvrirplustard, absentOK=True)
		EKOX(ce)
		EKOT("########################## logged in!!")
		EKOI(self.screen(), sz=800)					   



	def sched(self) :
		pass
		
	def renvoi_portable(self) :
		self.renvoi_numero("0685848778")

	def status(self) :
		self.renvoi_numero(None)

	def renvoi_secretariat(self) :
		EKO()
		self.renvoi_numero("0973017826")

	def renvoi_messagerie(self) :
		EKO()
		self.renvoi_numero(MESSAGERIE)
		
	def renvoi_messagerie_3(self) :
		EKO()
		self.renvoi_numero(MESSAGERIE_3)
			
	def renvoi_numero(self, num = None) :
		self.driver.set_window_size(1024, 1768)		
		renvoyer_vers_numero = num
		EKOX(renvoyer_vers_numero)
		self.login()
		EKO()
		# écran "votre espace client pro"
		# votre contrat
		#EKOI(self.screen(), sz=800)
		numero = "02 99 66 02 49"
		self.driver.implicitly_wait(5)
		EKO()
		self.do_click_txt(numero, 0, exact=True)
		time.sleep(2); EKOI(self.screen(), sz=800)		
		EKO()
		self.do_click_txt('Gérer votre ligne Fixe')
		EKO()
		time.sleep(2); EKOI(self.screen(), sz=800)				
		self.do_click_txt("Renvoi d'appel")
		time.sleep(2); EKOI(self.screen(), sz=800)				
		EKO()

		self.check_txt_visible("Tous les appels entrants")
		status = self.find_txt("Réinitialiser")
		status_p  = status.find_element(By.XPATH, '../..')
		#EKOX(dir(status_p))
		EKOX(status_p.get_attribute("innerText"))
		if num == self.MESSAGERIE_3 :
			self.do_click_txt("Les appels sur occupation")
			time.sleep(2); EKOI(self.screen(), sz=800)
			self.do_click_txt("Vers la messagerie")
			time.sleep(2); EKOI(self.screen(), sz=800)					
			self.do_click_txt("Continuer", num=1)
			time.sleep(2); EKOI(self.screen(), sz=800)
			self.do_click_txt("3 sonneries")
			time.sleep(2); EKOI(self.screen(), sz=800)
			self.do_click_txt("Continuer", num=1)
			time.sleep(2); EKOI(self.screen(), sz=800)
			self.do_click_txt("En permanence")
			time.sleep(2); EKOI(self.screen(), sz=800)
			self.do_click_txt("Valider")						
			time.sleep(2); EKOI(self.screen(), sz=800)

		else :
			self.do_click_txt("Tous les appels entrants")
			time.sleep(2); EKOI(self.screen(), sz=800)
			if num == self.MESSAGERIE :
				self.do_click_txt("Vers la messagerie")
				time.sleep(2); EKOI(self.screen(), sz=800)					
				self.do_click_txt("Continuer", num=1)
				time.sleep(2); EKOI(self.screen(), sz=800)
				self.do_click_txt("En permanence")
				time.sleep(2); EKOI(self.screen(), sz=800)					
				self.do_click_txt("Valider")
				time.sleep(2); EKOI(self.screen(), sz=800)
			elif num is not None :
				assert(num.isnumeric())
				self.do_click_txt("Vers un numéro")
				time.sleep(2); EKOI(self.screen(), sz=800)					
				self.do_click_txt("Continuer", num=1)
				time.sleep(2); EKOI(self.screen(), sz=800)
				EKO()
				num_area = self.find_txt("Saisissez votre numéro")
				num_area.click()
				num_area = self.find_txt("Saisissez votre numéro")
				num_area_p = num_area.find_element(By.XPATH, '..')
				num_area_pp = num_area_p.find_element(By.XPATH, '..')
				num_area_z = num_area_pp.find_elements(By.TAG_NAME, 'input')
				EKOX(len(num_area_z))
				num_area_z = num_area_z[0]
				try :
					num_area_z.send_keys(num)
				except Exception as e :
					EKOX(str(e))
				EKO()
				time.sleep(2); EKOI(self.screen(), sz=800)					
				EKOX(num_area_z.get_attribute("value"))
				self.do_click_txt("Continuer", num=1)
				time.sleep(2); EKOI(self.screen(), sz=800) 
				
			else :
				return status_p.get_attribute("innerText")
		EKO()
		time.sleep(2)
		#EKOI(self.screen(), sz=800)
		return num



class DummyRobotWeb(object):
	def __init__(self) :
		pass
	
	@cherrypy.expose
	def index(self):
		return "Hello World!"



class RobotWeb(object):
	def __init__(self, robot) :
		self.robot = robot
		self.no = 0
		
	@cherrypy.expose
	def index(self):
		return "Hello World!"

def sched() :
		p_date()

	
if __name__ == '__main__':
	EKO()
	robot = Robot()

	if True :
		try :
			d = [ ("secretariat", lambda : robot.renvoi_secretariat()),
				  ("portable", lambda : robot.renvoi_portable()),
				  ("status" , lambda : robot.status()),
				  ("messagerie", lambda : robot.renvoi_messagerie()),
				  ("mess 3", lambda : robot.renvoi_messagerie_3()),
				  ("secretariat", lambda : robot.renvoi_secretariat())
				  ]
			for m,f in d :
				EKON(m)
				r = f()
				EKOX(r)
				time.sleep(2); EKOI(robot.screen(), sz=800)	

			EKOX(r)
		except Exception as e :
			EKOX(str(e))
			traceback.print_exc()
			EKOX(traceback.print_stack())
				
	schedule = [
			("*/1 * * * 1,2,3,4,5,6,7", robot.sched),
			("0 8 * * 1,2,4,5", 	robot.renvoi_secretariat),
			("15 12 * * 1,2,4,5", 	robot.renvoi_messagerie_3),
			("50 12 * * 1,2,4,5", 	robot.renvoi_secretariat),
			("20 14 * * 1,2,4,5", 	robot.renvoi_portable),
			("30 15 * * 1,2,4,5", 	robot.renvoi_messagerie_3),
			("30 19 * * 1,2,4,5", 	robot.renvoi_secretariat),
			("0 8 * * 6", 			robot.renvoi_messagerie),
			("0 13 * * 6", 			robot.renvoi_secretariat),
			("0 8 * * 3", 			robot.renvoi_secretariat),
			("0 12 * * 3", 			robot.renvoi_messagerie),
			("0 19 * * 3", 			robot.renvoi_secretariat) ]
	p_date()
	while True:
			for e in schedule :
					if pycron.is_now(e[0]) :
							p_date()
							e[1]()
							time.sleep(60)               # The process should take at least 60 sec
                    # to avoid running twice in one minute
			else:
					time.sleep(15)               # Check again in 15 seconds

				
	if False : 
		cherrypy.server.socket_host = '192.168.1.5' # la tour , '0.0.0.0' # put it here 
		cherrypy.quickstart(RobotWeb(robot))
		robot.driver.close()
		EKO()
	#cherrypy.server.socket_host = '192.168.1.32' #'0.0.0.0' # put it here 


