from argparse import ArgumentParser
from flask import Flask, Response, render_template
from flask_apscheduler import APScheduler
from fs_scraper import scraper
from lewy_globals import colors as c
import lewy_api
import lewy_db
import lewy_globals
import lewy_routes
import os
import time

app = Flask(__name__)
app_host = "None"
app_port = "None"
scr = None

def setup():
	# sanity check: make sure config is set
	# required to make `flask --app lewy run --debug` work
	global config, app_host, app_port, scrape
	try:
		if not config['general']:
			lewy_globals.setConfig(lewy_globals.configfile)
			config = lewy_globals.config
	except:
		lewy_globals.setConfig(lewy_globals.configfile)
		config = lewy_globals.config

	# setting all the variables
	lewy_globals.starttime = int(time.time())
	lewy_globals.realUptime = 0
	lewy_globals.apiRequests = 0
	lewy_globals.apiFailedRequests = 0
	lewy_globals.isProxied = config['general']['is_proxied']
	lewy_globals.outsideApiHits = 0

	are_we_sure_of_host_and_port = True
	if app_host == "None":
		app_host = "127.0.0.1"
		are_we_sure_of_host_and_port = False
	if app_port == "None":
		app_port = "5000"
		are_we_sure_of_host_and_port = False

	public_facing_url = config['general']['public_facing_url']
	if len(public_facing_url) >= 4 and public_facing_url[0:5].lower() == "https":
		https_str  = f"{c.OKBLUE}INFO:{c.ENDC} You're trying to run this web server on HTTPS, but currently it's not possible to do that!\n"
		https_str += f"      Please consider running this service behind a reverse proxy if you need HTTPS.\n"
		print(https_str)
	rewrite_sanity_check = public_facing_url.replace(f"{app_host}:{app_port}", "")
	if not config['general']['is_proxied'] and public_facing_url == rewrite_sanity_check:
		sanity_string  = f"{c.OKBLUE}INFO:{c.ENDC} Public facing URL does not match the IP and port the server is running on.\n"
		sanity_string += f"      Expected: {c.OKCYAN}{config['general']['public_facing_url']}{c.ENDC}, but" 
		if not are_we_sure_of_host_and_port: sanity_string += " (assuming it's)"
		sanity_string += f" running on: {c.OKCYAN}{app_host}:{app_port}{c.ENDC}.\n"
		sanity_string += f"      This is just a sanity check and may not neccessarily mean bad configuration.\n"
		sanity_string += f"      If you're running a reverse proxy, set {c.OKCYAN}is_proxied{c.ENDC} to true to silence this message.\n"
		print(sanity_string)

	# Should fix disconnects: https://stackoverflow.com/a/61739721
	app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {"pool_pre_ping": True}
	app.config['SQLALCHEMY_DATABASE_URI'] = f"{config['general']['db_path_url']}"
	app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
	
	# Widoki widoczne dla "normalnego" użytkownika:
	app.add_url_rule('/',                           view_func=lewy_routes.index)
	app.add_url_rule('/index.html',                 view_func=lewy_routes.index)
	app.add_url_rule('/mecze',                      view_func=lewy_routes.mecze)
	app.add_url_rule('/statystyki',                 view_func=lewy_routes.statystyki)
	app.add_url_rule('/toggle_dark_mode',     	 	view_func=lewy_routes.toggle_dark_mode)
	app.add_url_rule('/club',       				view_func=lewy_routes.clubs)
	app.add_url_rule('/representation',       		view_func=lewy_routes.representation)
	app.add_url_rule('/compare',       				view_func=lewy_routes.compare)
	app.add_url_rule('/trophies',       			view_func=lewy_routes.trophies)
	
	# API:
	app.add_url_rule('/api/',                        view_func=lewy_api.api_greeting)
	app.add_url_rule('/api/<path:received_request>', view_func=lewy_api.api_global_catchall)
	
	db = lewy_globals.setupDb(app, config)
	scr = scraper()

	with app.app_context():
		db.create_all()

	# job scheduler for repetetive tasks
	scheduler = APScheduler()
	scheduler.add_job(func=every5seconds, trigger='interval', id='5sec', seconds=5)
	scheduler.add_job(func=every2hours,   trigger='interval', id='2hr',  hours=2)
	scheduler.start()

# gets called every 5 seconds
def every5seconds():
	# update the "real" uptime counter
	lewy_globals.realUptime += 5

def every2hours():
	# zaktualizuj bazę danych scrapując FS
	scr.aktualizuj_dane()
	return

@app.route('/<string:val>', methods=['GET'])
def blank(val):
	return Response(f"{val}: not implemented in lewangoalski {lewy_globals.getCommitWithFailsafe()}", mimetype="text/plain")

def main(args):
	print(f"{c.BOLD + c.HEADER}Witaj w webaplikacji 'lewangoalski' ({lewy_globals.getCommitWithFailsafe()})!{c.ENDC}")
	print(f"Aby uruchomić w trybie deweloperskim (aby włączyć automatyczne przeładowanie zmian), użyj: {c.OKCYAN}flask --app lewy run --debug{c.ENDC}.")
	print( "Aby uruchomić lokalnie, użyj adresu IP 127.0.0.1. Aby uruchomić na każdym z interfejsów, użyj 0.0.0.0.\n")
	
	global config, app_host, app_port
	try:
		# if specified, use custom config file
		lewy_globals.configfile = args.config
		lewy_globals.setConfig(lewy_globals.configfile)

	except:
		# if not, try using the default "config.toml"
		if os.path.exists("config.toml"):
			lewy_globals.configfile = "config.toml"
		else:
			# unless it's not there, if that's the case then use the dummy file
			lewy_globals.configfile = ""
		# but try to set the API secret if provided by the user
		if args.secret:
			lewy_globals.randomly_generated_passcode = args.secret
		lewy_globals.setConfig(lewy_globals.configfile)

	config = lewy_globals.config

	try:
		host = args.ip
		port = args.port
		if not host or not port:
			raise Exception 
	except:
		config_ip, config_port = lewy_globals.extractIpAndPortFromPublicUrl()
		print(f"Wpisz nazwę_hosta:port, na których należy uruchomić serwer Flask [domyślnie: {config_ip}:{config_port}]:")
		try:
			host_port = input('> ').split(':')
			if host_port == ['']:
				host_port = [config_ip, config_port] # defaults

		except KeyboardInterrupt:
			print(" ...wychodzę z programu."), quit() # handle Ctrl+C

		host = host_port[0]
		port = host_port[1]
	
	print()

	app_host = host
	app_port = port

	setup()
	app.run(host=host, port=int(port))


if __name__ == "__main__":
	#app.run(host="127.0.0.1", port=5000)
	#app.run(host="0.0.0.0", port=5000)
	parser = ArgumentParser(description='Aplikacja webowa do śledzenia statystyk Roberta Lewandowskiego.')

	parser.add_argument("-i", "--ip",     dest="ip",     help="ip address/interface to bind to")
	parser.add_argument("-p", "--port",   dest="port",   help="port on which the flask web backend should be ran")
	parser.add_argument("-c", "--config", dest="config", help="path to TOML config file")
	parser.add_argument("-s", "--secret", dest="secret", help="API key for resource access") # NOT tested

	args = parser.parse_args()

	main(args)

else:
	app_host = os.getenv("FLASK_RUN_HOST", "None")
	app_port = os.getenv("FLASK_RUN_PORT", "None")
	setup()