#
# Copyright (c), 2015-2016, Quantum Espresso Foundation and SISSA (Scuola
# Internazionale Superiore di Studi Avanzati). All rights reserved.
# This file is distributed under the terms of the MIT License. See the
# file 'LICENSE' in the root directory of the present distribution, or
# http://opensource.org/licenses/MIT.
# Authors: Davide Brunato, Giovanni Borghi
#
"""
Conversion functions for Quantum Espresso input options.
"""
import logging
from .exceptions import ConfigError
# from .utils import set_logger
logger = logging.getLogger('qespresso')
#
# Other derived values
[docs]def get_starting_magnetization(name, **kwargs):
    """
    Build starting magnetization vector from species data.
    :param name: parameter name
    :param kwargs:
    :return: string
    """
    try:
        atomic_species = kwargs['atomic_species']
        species = atomic_species['species']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return []
    lines = []
    try:
        lines.append(' {0}(1)={1}'.format(
            name, species.get('starting_magnetization', 0.0)))
    except AttributeError:
        k = 0
        for specie in species:
            k += 1
            lines.append(' {0}({1})={2}'.format(
                name, k, specie.get('starting_magnetization', 0.0)))
    return lines 
[docs]def get_system_nspin(name, **kwargs):
    """
    Get the value for 'nspin' parameter of the SYSTEM namelist.
    :param name:
    :param kwargs:
    :return:
    """
    try:
        lsda = kwargs['lsda']
        if lsda:
            return [' nspin=2']
        noncolin = kwargs['noncolin']
        if noncolin:
            return [' nspin=4']
        else:
            return [' nspin=1']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return [] 
[docs]def set_ibrav_to_zero(name, **kwargs):
    line = '  ibrav = 0'
    return [line] 
[docs]def get_system_eamp(name, **kwargs):
    """
    :param name:
    :param kwargs:
    :return:
    """
    try:
        electric_potential = kwargs['electric_potential']
        if electric_potential in ('Berry_Phase', 'homogenous_field'):
            return []
        electric_field_amplitude = kwargs['electric_field_amplitude']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return []
    if electric_potential == 'sawtooth_potential':
        return [' eamp={0}'.format(electric_field_amplitude)]
    else:
        return [] 
[docs]def get_electrons_efield(name, **kwargs):
    """
    :param name:
    :param kwargs:
    :return:
    """
    try:
        electric_potential = kwargs['electric_potential']
        if electric_potential in ('Berry_Phase', 'sawtooth_potential'):
            return []
        electric_field_amplitude = kwargs['electric_field_amplitude']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return []
    if electric_potential == 'homogenous_field':
        return [' efield={0}'.format(electric_field_amplitude)]
    else:
        return [] 
[docs]def get_system_edir(name, **kwargs):
    """
    :param name:
    :param kwargs:
    :return:
    """
    try:
        electric_potential = kwargs['electric_potential']
        electric_field_direction = kwargs['electric_field_direction']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return []
    if electric_potential == 'sawtooth_potential':
        return [' edir={0}'.format(electric_field_direction)]
    else:
        return [] 
[docs]def get_control_gdir(name, **kwargs):
    """
    :param name:
    :param kwargs:
    :return:
    """
    try:
        electric_potential = kwargs['electric_potential']
        electric_field_direction = kwargs['electric_field_direction']
    except KeyError as err:
        logger.error("Missing required arguments when building "
                     "parameter '%s'! %s" % (name, err))
        return []
    if electric_potential in ('homogenous_field', 'Berry_Phase'):
        return [' gdir={0}'.format(electric_field_direction)]
    else:
        return [] 
[docs]def get_cell_dofree(name, **kwargs):
    """
    :param name:
    :param kwargs:
    :return:
    """
    try:
        fix_volume = kwargs['fix_volume']
    except KeyError:
        fix_volume = False
    try:
        fix_area = kwargs['fix_area']
    except KeyError:
        fix_area = False
    try:
        fix_xy = kwargs['fix_xy']
    except KeyError:
        fix_xy = False
    try:
        isotropic = kwargs['isotropic']
    except KeyError:
        isotropic = False
    vals = [fix_volume, fix_area, fix_xy, isotropic]
    cell_dofree = "cell_dofree = 'all'"
    if vals.count(True) > 1:
        logger.error("only one of fix_volume, fix_area, fix_xy and isotropic "
                     "can be true")
        return [cell_dofree]
    if fix_volume:
        cell_dofree = "cell_dofree = 'shape'"
    if fix_area:
        cell_dofree = "cell_dofree = '2Dshape'"
    if fix_xy:
        cell_dofree = "cell_dofree = '2Dxy'"
    if isotropic:
        cell_dofree = "cell_dofree = 'volume' "
    return [cell_dofree] 
[docs]def neb_set_system_nat(name, **kwargs):
    """
    Extract SYSTEM[nat] from the first element of the list of atomic_structure
    :param name: Variable name
    :param kwargs: list of dictionaries each containing an atomic_structure element
    :return: list containin one string to be printed in system name list nat = nat_value
    """
    images = kwargs.get('atomic_structure', [])
    if len(images) < 1:
        logger.error('No atomic_structure element found !!!')
        return ''
    image = images[0]
    nat_value = int(image.get('nat', 0))
    if nat_value <= 0:
        logger.error("error reading nat value from atomic_structure !!!")
        return ''
    return [' nat = {0}'.format(nat_value)] 
[docs]def Ha2Ry(name, **kwargs):
    related_tag = kwargs['_related_tag']
    value = kwargs[related_tag] * 2.e0
    return [' {} = {:12.8f}'.format(name, value)] 
[docs]def setOneAmassLine(name, **kwargs):
    lines = []
    try:
        node = kwargs['amass']
        value = float(node['_text'])
        index = node['atom']
        lines.append(' {}({})={:7.3f}'.format(name, index, value))
    except TypeError:
        for node in kwargs['amass']:
            value = float(node['_text'])
            index = node['atom']
            lines.append(' {}({})={:7.3f}'.format(name, index, value))
    return lines 
[docs]def set_lda_plus_u_flag(name, **kwargs):
    lines = []
    related_tag = kwargs['_related_tag']
    related_data = kwargs[related_tag]
    for value in iter(
            related_data if isinstance(related_data, list) else [related_data]):
        if value.get('label') == "no Hubbard" or value['_text'] <= 0:
            continue
        lines.append('lda_plus_u = .t.')
        break
    return lines 
[docs]def set_boolean_flag(name, **kwargs):
    lines = []
    related_tag = kwargs['_related_tag']
    related_data = kwargs[related_tag]
    if related_data in ['true', 'True', 'TRUE']:
        lines.append(' %s = .true.' % related_tag)
    else:
        lines.append(' %s = .false.' % related_tag)
    return lines 
[docs]def set_what_td_calculation(name, **kwargs):
    return [kwargs['whatTD']]