"""Config parser for fingerprint filtering and 3d model generation application.

.. moduleauthor:: xlanro00

"""

from os.path import exists  
import json
import hashlib
import log

def save_preset(filters, params, preset_name):
    '''Save filter list from command line to database.

    :param filters: list of filters to be saved
    :param preset_name: name of preset to be saved
    '''
    filt = {}
    # Create dictionary of filter parameters
    for i, filter in enumerate(filters):
        
        filt[i] = {}
        filt[i]["name"] = filter
        for key, value in params[i+1].items():
            if value is not None:
                filt[i][key] = value

    new_filt = []
    for i, filter in enumerate(filt):
        new_filt.append(filt[filter])
    log.print_message("Saving filters as:", preset_name)

    # Store preset to database
    store_to_db(new_filt, preset_name)


def store_to_db(preset, preset_name):
    '''Store filter preset to database.

    :param preset: dictionary of filter preset to be stored
    :param preset_name: name of preset to be stored
    '''

    # Create unique id for preset, this serves to avoid duplicit preset entries
    id = str(hashlib.md5(str(preset).encode('utf-8')).hexdigest())[:8]
    preset_name = preset_name + "_" + id
    # Create json object from preset
    preset = json.dumps({preset_name: preset}, indent=4)
    preset = json.loads(preset)

    # If database doesn't exist, create it
    if not exists("conf/db.json"):
        log.print_message("Storing preset to database")
        with open("conf/db.json", 'w') as db:
            json.dump(preset, db)
    else:
        # If database exists, load it and check if preset already exists
        try:
            with open("conf/db.json", 'r') as db:
                db_presets = json.load(db)

        # Empty file is an error, so we don't read it
        except json.decoder.JSONDecodeError:
            db_presets = {}

        # If preset already exists, skip it
        if preset_name in db_presets:
            log.print_message("Preset already exists in database, skipping")
        else:
            log.print_message("Storing preset to database")
            db_presets.update(preset)
        
        # Finally write the updated entries to db file
        with open("conf/db.json", 'w') as db:
            json.dump(db_presets, db, indent=4)


def parse_conf(preset_name, filters, params, config_file):
    '''Parse configuration file if one was specified.

    :param preset_name: preset name to be loaded
    :param filters: list of filters to be loaded
    :param params: dictionary of filter parameters to be loaded
    :param config_file: path to config file
    '''

    if not exists(config_file):
        log.error_exit("Config file not found")

    config = json.load(open(config_file))
    
    # Find preset in config file
    if preset_name in config:
        filter_array = config[preset_name]
        store_to_db(filter_array, preset_name)
        # Iterate over filters in preset, store them and their parameters
        for i, filter in enumerate(range(len(filter_array)), start=1):
            filters.append(filter_array[filter]["name"])
            params[i] = {}
            for attribute, value in filter_array[filter].items():
                # Filter name isn't needed in here
                if attribute != "name":
                    params[i][attribute] = value
            parse_params(params[i])

        log.print_message("Loaded preset:", preset_name,
                "from file:", config_file)
    else:
        log.error_exit("Preset not found in config file")


def parse_params(params):
    '''Parse parameters of filters. Set to None if parameter is not specified.
    These are later set to default values in the filter method apply.

    :param params: dictionary of filter parameters
    '''

    possible_params = {"sigma", "ksize", "kernel", 
                       "diameter", "sigmaColor", "sigmaSpace", 
                       "patch_size", "patch_distance", "weight", 
                       "amount", "radius", "percent", 
                       "threshold", "h",
                       "margin", "color"
                       }

    for key in possible_params:
        if params.get(key) is None:
            params[key] = None
        else:
            params[key] = params[key]

