import bpy
from .utils_debug import debug_err
from . import utils #import getSchemesDirectory, getWebProjectPath, isSchemeFile
import json
import os

debug = False

# schemes contain the properties a component has
# it is used to create the type and the panel
schemes = {}
schemes_lowercaseMap = {}
# registered types
types = {}

def getTypes():
    return types

def getSchemes():
    return schemes

def isKnown(schemeName: str):
    # schemeName = schemeName.lower()
    return schemeName in schemes

def isMissing(componentName: str):
    return componentName not in schemes

def getScheme(componentName: str):
    if componentName.startswith("NEEDLE_component_"):
        componentName = componentName[17:]
    componentName = componentName.lower()
    global schemes_lowercaseMap, schemes
    if componentName in schemes_lowercaseMap:
        return schemes[schemes_lowercaseMap[componentName]]
    return None

def addSchemesFromFile(schemePath: str):
    global debug
    # check if file exists
    if os.path.isfile(schemePath) and schemePath.endswith(".json"):
        if debug:
            print("→ Load schemes from: " + schemePath)
        with open(schemePath) as f:
            try:
                newScheme = json.load(f)
                # iterate and add schemes
                for key in newScheme:
                    componentScheme = newScheme[key]
                    # print("Found component scheme: " + key, componentScheme)
                    newObj = {}
                    # make sure enabled is always there and the first prop
                    newObj["enabled"] = {"type": "bool", "value": True}
                    # add properties
                    for prop in componentScheme:
                        newObj[prop] = componentScheme[prop]
                    newScheme[key] = componentScheme = newObj
                    schemes_lowercaseMap[key.lower()] = key
                    # check if scheme already exists
                    if key in schemes:
                        # combine
                        schemes[key].update(componentScheme)
                    else:
                        schemes[key] = componentScheme
            except Exception as e:
                debug_err("Error loading scheme file: " + schemePath + "\n", e)
                fileName = os.path.basename(schemePath)
                utils.showMessage(["Error generating component scheme", fileName, e], "Failed Generating Component")
    else:
        print("Scheme file not found: " + schemePath)


# load schemes from json
def internal_LoadSchemes():
    global schemes, schemes_lowercaseMap, debug
    schemes = {}
    schemes_lowercaseMap = {}
    path = os.path.join(os.path.dirname(__file__), 'data', 'schemes.json')
    # check if file exists
    if os.path.isfile(path):
        with open(path) as f:
            schemeSources = json.load(f)
            for schemePath in schemeSources:
                # check if absolute or relative path
                if not os.path.isabs(schemePath):
                    schemePath = os.path.join(
                        os.path.dirname(__file__), 'data', schemePath)
                addSchemesFromFile(schemePath)
    else:
        print("SCHEMES LIST NOT FOUND")

    if utils.webProjectExists():
        # print("LOAD SCHEMES FROM: " + path)
        webProjectPath = utils.getWebProjectPath()

        if webProjectPath is not None:
            if debug:
                print("LOAD SCHEMES FROM WEB PROJECT")
            schemesDirectory = utils.getSchemesDirectory(webProjectPath)
            if schemesDirectory is not None and os.path.exists(schemesDirectory):
                for file in os.listdir(schemesDirectory):
                    if utils.isSchemeFile(file):
                        addSchemesFromFile(os.path.join(schemesDirectory, file))

    # sort schemes alphabetically
    schemes = dict(sorted(schemes.items(), key=lambda item: item[0]))


def loadSchemes():
    internal_LoadSchemes()


def unregister():
    for key in types:
        try:
            bpy.utils.unregister_class(types[key])
        except RuntimeError:
            pass
    types.clear()
