import os
import uuid
import subprocess
import requests
import threading
import json
from urllib.parse import urlparse, urlunparse, urljoin

import shepherd.plugin
# Check for shepherd.new file in edit conf dir. If there,
# or if no shepherd.id file can be found, generate a new one. 
# For now, also attempt to delete /var/lib/zerotier-one/identity.public and identity.secret
# Once generated, if it was due to shepherd.new file, delete it.


#Start new thread, and push ID and core config to api.shepherd.distreon.net/client/update

client_id = None
control_url = None
api_key = None

def _update_job(core_config, plugin_config):
    payload = {"client_id":client_id, "core_config":core_config,"plugin_config":plugin_config}
    #json_string = json.dumps(payload)
    try:
        # Using the json arg rather than json.dumps ourselves automatically sets the Content-Type 
        # header to application/json, which Flask expects to work correctly
        r = requests.post(control_url, json=payload, auth=(client_id, api_key))
    except requests.exceptions.ConnectionError:
        raise

def generate_new_zerotier_id():
    print("Removing old Zerotier id files")
    try:
        os.remove("/var/lib/zerotier-one/identity.public")
        os.remove("/var/lib/zerotier-one/identity.secret")
    except:
        pass
    print("Restarting Zerotier systemd service to regenerate ID")
    subprocess.run(["systemctl", "restart", "zerotier-one.service"])

def generate_new_id(root_dir):
    global client_id
    with open(os.path.join(root_dir, "shepherd.id"), 'w+') as f:
        new_id = uuid.uuid1()
        client_id = str(new_id)
        f.write(client_id)
    generate_new_zerotier_id()

def init_control(core_config, plugin_config):
    global client_id
    global control_url
    global api_key

    root_dir = os.path.expanduser(core_config["root_dir"])
    editconf_dir = os.path.dirname(os.path.expanduser(core_config["conf_edit_path"]))

    #Some weirdness with URL parsing means that by default most urls (like www.google.com)
    # get treated as relative
    # https://stackoverflow.com/questions/53816559/python-3-netloc-value-in-urllib-parse-is-empty-if-url-doesnt-have

    control_url = core_config["control_server"]
    if "//" not in control_url:
        control_url = "//"+control_url
    control_url = urlunparse(urlparse(control_url)._replace(scheme="https"))
    control_url = urljoin(control_url, "/client/update")
    print(F"Control url is: {control_url}")

    api_key = core_config["api_key"]

    if os.path.isfile(os.path.join(editconf_dir, "shepherd.new")):
        generate_new_id(root_dir)
        os.remove(os.path.join(editconf_dir, "shepherd.new"))
        print(F"Config hostname: {core_config['hostname']}")
        if not (core_config["hostname"] == ""):
            print("Attempting to change hostname")
            subprocess.run(["raspi-config", "nonint", "do_hostname", core_config["hostname"]])
    elif not os.path.isfile(os.path.join(root_dir, "shepherd.id")):
        generate_new_id(root_dir)
    else:
        with open(os.path.join(root_dir, "shepherd.id"), 'r') as id_file:
            client_id = id_file.readline().strip()

    print(F"Client ID is: {client_id}")

    control_thread = threading.Thread(target=_update_job, args=(core_config,plugin_config))
    control_thread.start()
        

def _post_logs_job():
    logs = shepherd.plugin.plugin_functions["scout"].get_logs()
    measurements = shepherd.plugin.plugin_functions["scout"].get_measurements()


    payload = {"client_id":client_id, "logs":logs, "measurements":measurements}
    
    try:
        r = requests.post(control_url, json=payload, auth=(client_id, api_key))
    except requests.exceptions.ConnectionError:
        pass

def post_logs():
    post_logs_thread = threading.Thread(target=_post_logs_job, args=())
    post_logs_thread.start()