import requests, json

def get_md_from_datacite( doi ) : 
    """
	retrieve data research metadata from datacite
    """

    req = requests.get( f"https://api.datacite.org/dois/{doi}" )

    try : 
    	res = req.json()
    except : 
    	return "error"

    if "errors" in res : 
    	return "error"

    return res   


def parse_value_following_instruction(key, instruction, datacite_content) : 
    """
    permet de récuéprer les données reçues depuis datacite avec leur propre sturcturation selon les instructions précisées manuellement
    key : la clé à traiter
    instruction : les instructions à appliquer pour récupérer la valeur de la clé
    datacite_content : le contenu de datacite à la clé précisé

    la recherche des instructions est effectuée notamment depuis leur type (string ou dict) : à revoir pour plus de cohérence
    """

    buffer = {}  ## pour récupérer les données avec un dictionnaire
    
    ## quand les données à récupérer sont des objets simples, on récupère simplement la valeur
    if instruction == "string" or instruction == "int" :
        return {key: datacite_content}
        
    ## qaund les instructions sont fomratées en dict
    if isinstance(instruction, dict) :
        
        ## si past_values_w_this_key est dans les instructions
        if "past_values_w_this_key" in instruction :
            ## pour débbugger 
            ##print("attribute is", key)

            ## quand les données sont directement sous forme de dict (eg. datatype)
            if instruction["past_values_w_this_key"] in datacite_content :
                temp_key_to_get = instruction["past_values_w_this_key"]
                 
                buffer.update(
                    { instruction["past_values_w_this_key"] : datacite_content[temp_key_to_get] }
                )
            
            ## quand les données sont des listes et qu'il faut itérer dessus
            else : 
                all_vals = []
                temp_key_to_get = instruction["past_values_w_this_key"]
                [all_vals.append( item[ temp_key_to_get ]) for item in datacite_content]
                           
                buffer.update(
                    {temp_key_to_get : ",".join(all_vals)}
                )

            ## quand il faut sortir toutes les données brutes
            if "flatten_all_in_this_key" in instruction : 
                buffer.update(
                    {instruction["flatten_all_in_this_key"] : str(datacite_content) }
                )
                
        ## if past_first_occ in instruction
        if "past_first_occ" in instruction : 
            temp_key_to_get = instruction["past_first_occ"]
            buffer.update(
                {temp_key_to_get: datacite_content[0][temp_key_to_get]}
            )

        ## if go_to_sub_key in the instruction
        if "go_to_sub_key" in instruction :
            
            temp_parent_key_to_get = instruction["go_to_sub_key"]
            ## identifier les clés enfantes à retrouver dans dataCite
            temp_child_key_to_get = instruction["get_key"]
            
            buffer.update(
                {key : datacite_content[temp_parent_key_to_get][temp_child_key_to_get] }
            )
            
    else : 
        buffer.update(
            {key : "to_do"}
        )
        
    return buffer     



def parse_datacite_md(raw_datacite_mds):
    """
    from json file load instruction
    from DOI get datacite cotent
    iterate on all datacite attributes
        if data from datacite is needed get it with parse_value_following_instruction()
    iterate on all datacite relationship
        if data from datacite is needed get it with parse_value_following_instruction()
    """
    doi_md = {
    "doi" : raw_datacite_mds["data"]["id"]
    }
    
    ## ____0____ from json file load instructions
    with open("datacite-parser-instructions.json") as parser_file : 
        datacite_parser = json.load(parser_file)

    ## liste de tous les attributs à récupérer
    attributes_to_get = datacite_parser["path-and-fields"]["attributes"].keys()
    relations_to_get = datacite_parser["path-and-fields"]["relationships"].keys()

    ## ____1___ iterate on datacite attributes
    for attribute_key in raw_datacite_mds["data"]["attributes"] :
        attribute_value = raw_datacite_mds["data"]["attributes"][attribute_key]

        ## ne pas prendre les valeurs si elles sont nulles (sauf pour les nb)
        if not isinstance(attribute_value, int) and not attribute_value : 
            # pour suivi print(f"{attribute_key} is empty")
            continue
       
        ## si l'attribut fait parti de ceux à récupérer
        if attribute_key in attributes_to_get : 
            
            ## redistribuer le nom de la clé et sa valeur
            value_to_add = parse_value_following_instruction(
                attribute_key,
                datacite_parser["path-and-fields"]["attributes"][attribute_key], 
                attribute_value)
            
            doi_md.update(value_to_add)

    
    ## ____2___ iterate on datacite relations
    ### nb : on pourrait alléger en regroupant attribut et relationships
    for relation_key in raw_datacite_mds["data"]["relationships"] :
        relation_value = raw_datacite_mds["data"]["relationships"][relation_key]
        
        ## ne pas prendre les valeurs si elles sont nulles (sauf pour les nb)
        if not isinstance(relation_key, int) and not relation_value : 
            continue
        
        ## si la relation est préciser dans les instructions
        if relation_key in relations_to_get :
            ## to debug print("relation is", relation_key)
            relation_to_add = parse_value_following_instruction(
                relation_key,
                datacite_parser["path-and-fields"]["relationships"][relation_key], 
                relation_value
            )
            doi_md.update(relation_to_add)
            
    return doi_md


def from_repos_load_dois(repo_list) :
	"""
	from repo name (eg Zenodo) load file
	"""
	dois_raw = []

	## load all dois
	for repo_name in repo_list : 
		dois_raw += load_dois_from_file(repo_name)

	return dois_raw


def load_dois_from_file(repo_name) :
    """
	charge les dois des fichiers texts
	file name syntax "entrepot-dois.txt"
	"""

    file_name = repo_name + "-dois.txt"
    folder_path = "../0-collect-data/"
    dois_in_repo = []

    with open(folder_path + file_name) as f:
        ## attention à la fin des lignes il y a un retour à la ligne, d'où le (line)-1
        ## on passer les DOI en miniscule également
        [dois_in_repo.append( line[ :len(line)-1].lower()) for line in f.readlines()]
	
    print(f"{repo_name} DOIs \t\t {len(dois_in_repo)}")
	
    return dois_in_repo