import datetime

from .utils_addon_data import getAddonMetaPath

from .settings_addon import getAddonPreferences
from .__meta__ import getVersion
import requests
import bpy
import os
import getpass
import socket
import platform
import gpu

from .utils import isWindows
from .utils_debug import debug_err, debug_log, isDevEnvironment

# did_start = 0
analytics_localhost = False
last_start = 0

def send_analytics_started():
    global last_start
    if last_start == 0:
        if isDevEnvironment(): 
            debug_log("Addon directory name is 'addon'... (ignoring analytics start)")
            return
    now_in_seconds = datetime.datetime.now().timestamp()
    last_start = now_in_seconds
    bpy.app.timers.register(_delayed_send_analytics_started, first_interval=1.0)

def _delayed_send_analytics_started():
    try:
        data = __getData()
        __send("/new/editor_start", data)
    except Exception as e:
        debug_err(e)
    pass

def send_analytics_installation():
    try:
        data = __getData()
        meta_dir = getAddonMetaPath()
        path = os.path.join(meta_dir, "installation_analytics")
        if os.path.exists(path):
            debug_log("already sent installation analytics because file exists at " + path)
            return
        with open(path, "w") as f:
            f.write("sent at " + str(datetime.datetime.now()))
        debug_log("wrote installation analytics to " + path)
        __send("/new/installation", data)
        pass
    except Exception as e:
        debug_err("Failed to send installation analytics", e)
        pass


def send_new_export(exportPath, export_duration):
    try:
        data = __getData()
        blendfilename = bpy.path.basename(bpy.context.blend_data.filepath)
        data["projectPath"] = exportPath
        data["projectName"] = blendfilename
        data["buildDuration"] = export_duration
        # file count in exportpath
        filesInfo = __getTotalFilesInfo(exportPath)
        data["totalFilesCount"] = filesInfo[0]
        data["totalFilesSize"] = filesInfo[1] / 1024 / 1024 # in MB
        __send("/new/export", data)
    except Exception as e:
        debug_err("Failed to send export analytics", e)
    pass

def __getTotalFilesInfo(path):
    total = 0
    totalSize = 0
    for root, dirs, files in os.walk(path):
        total += len(files)
        for file in files:
            totalSize += os.path.getsize(os.path.join(root, file))
    return (total, totalSize)

def __getData():
    osInformation = __getOsInformation()
    addonPreferences = getAddonPreferences()
    licenseEmail = ""
    licenseKey = ""

    # userinfo = getUserInformation()
    # if addonPreferences:
    #     licenseEmail = addonPreferences.email
    #     licenseKey = addonPreferences.invoiceId
    data = {
        "editor": "blender",
        "editorVersion": bpy.app.version_string,
        "userName": __tryGetUserName(),
        "ipAddress": __tryGetIpAddress(),
        # disabled for now because it's super slow and blocking sometimes
        # "externalIpAddress": __tryGetPublicIpAddress(),
        "exporterVersion": getVersion(),
        "licenseEmail": licenseEmail,
        "licenseKey": licenseKey,
    }
    data = {**data, **osInformation}
    return data
        


backend_url = None
def __initBackendUrl():
    global backend_url, analytics_localhost
    backend_url = ""
    try:
        endpointResponse = requests.get("https://urls.needle.tools/analytics-endpoint-v2").text
        addon_install_path = os.path.dirname(os.path.realpath(__file__))
        print("Get analytics endpoint: ", addon_install_path)
        # if the addon is installed in the blender directory use the backend url from the endpoint response
        if analytics_localhost == False or not "needle-engine-blender" in addon_install_path:
            backend_url = endpointResponse + "/api/v2"
            # debug_log("Use analytics backend:", backend_url)
        else:
            backend_url = "http://localhost:3000/api/v2"
            debug_log("Use local analytics backend:", backend_url)
    except Exception as e:
        debug_err("Failed to get analytics endpoint", e)
        
__initBackendUrl()
        
def __send(endpoint, data):
    global backend_url
    if backend_url is None:
        __initBackendUrl()
    url = backend_url + endpoint
    req = requests.post(url, json=data)


def __tryGetUserName():
    # first we try to get the blender id
    blender_version = bpy.app.version_string
    blender_version = blender_version.replace(" ", "")
    blender_version_major_minor = blender_version.split(".")[0] + "." + blender_version.split(".")[1]
    # https://docs.blender.org/manual/en/latest/addons/system/blender_id.html
    if isWindows():
        path = "%AppData%\\Blender Foundation\\Blender\\" + blender_version_major_minor + "\\config\\blender_id"
        path = os.path.expandvars(path)
        print("> Blender Id path is " + path)
        if os.path.exists(path):
            with open(path, "r") as f:
                for line in f.readlines():
                    if "blender_id" in line:
                        return line.split(" ")[-1].strip()
                    
    # get OS username
    return getpass.getuser()
        


def __tryGetIpAddress():
    # https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
    return socket.gethostbyname(socket.gethostname())

__publicIpAddress = None
def __tryGetPublicIpAddress():
    global __publicIpAddress
    if __publicIpAddress is not None:
        return __publicIpAddress
    url = "https://api.ipify.org/"
    try:
        externalIpString = requests.get(url).text
        __publicIpAddress = externalIpString.strip()
        return __publicIpAddress
    except Exception as e:
        __publicIpAddress = ""
        debug_err("Failed to get public ip address", e)
        return None

def __getOsInformation() -> dict:
    try:
        information = {
            "os": platform.platform(terse=True),
            "osDeviceName": platform.node(),
            "osUserName": getpass.getuser(),
            "graphicsDevice": gpu.platform.renderer_get(),
            "systemLanguage": bpy.context.preferences.view.language,
        }
        if "userdomain" in os.environ:
            information["osDomainName"] = os.environ['userdomain']
        # deviceList = bpy.context.preferences.addons["cycles"].preferences.get_devices()
        # foundGraphicsDevice: bool = False
        # for deviceTuple in deviceList:
        #     if foundGraphicsDevice: break
        #     for device in deviceTuple:
        #         if device.type == "GPU":
        #             foundGraphicsDevice = True
        #             information["graphicsDevice"] = device.name
        #             break
        
        # print(information)
        return information
    except Exception as e:
        debug_err("Failed to get os information", e)
        return {}