# coding: utf-8
# Copyright (c) Pymatgen Development Team.
# Distributed under the terms of the MIT License.

from __future__ import division, unicode_literals
from pymatgen.analysis.chemenv.utils.scripts_utils import strategies_class_lookup
from os.path import expanduser, exists
from os import makedirs
import json
from six.moves import input
from pymatgen import SETTINGS

"""
This module contains the classes for configuration of the chemenv package.
"""

__author__ = "David Waroquiers"
__copyright__ = "Copyright 2012, The Materials Project"
__credits__ = "Geoffroy Hautier"
__version__ = "2.0"
__maintainer__ = "David Waroquiers"
__email__ = "david.waroquiers@gmail.com"
__date__ = "Feb 20, 2016"



class ChemEnvConfig():
    """
    Class used to store the configuration of the chemenv package :
     - Materials project access
     - ICSD database access
     - Default options (strategies, ...)
    """
    DEFAULT_PACKAGE_OPTIONS = {'default_strategy': {'strategy': 'SimplestChemenvStrategy',
                                                    'strategy_options': {'distance_cutoff': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_DISTANCE_CUTOFF,
                                                                         'angle_cutoff': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_ANGLE_CUTOFF,
                                                                         'additional_condition': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_ADDITIONAL_CONDITION,
                                                                         'continuous_symmetry_measure_cutoff': strategies_class_lookup['SimplestChemenvStrategy'].DEFAULT_CONTINUOUS_SYMMETRY_MEASURE_CUTOFF}},
                               'default_max_distance_factor': 1.5
                               }

    def __init__(self, package_options=None):
        if SETTINGS.get("PMG_MAPI_KEY", "") != "": 
            self.materials_project_configuration = SETTINGS.get("PMG_MAPI_KEY", "")
        else:
            self.materials_project_configuration = None


        if package_options is None:
            self.package_options = self.DEFAULT_PACKAGE_OPTIONS
        else:
            self.package_options = package_options

    def setup(self):
        while True:
            print('\n=> Configuration of the ChemEnv package <=')
            print('Current configuration :')
            if self.has_materials_project_access:
                print(' - Access to materials project is configured (add test ?)')
            else:
                print(' - No access to materials project')
            print(' - Package options :')
            for key, val in self.package_options.items():
                print('     {}   :   {}'.format(str(key), str(val)))
            print('\nChoose in the following :')
            print(' <1> + <ENTER> : configuration of the package options (strategy, ...)')
            print(' <q> + <ENTER> : quit without saving configuration')
            test = input(' <S> + <ENTER> : save configuration and quit\n ... ')
            if test == '1':
                self.setup_package_options()
            elif test == 'q':
                break
            elif test == 'S':
                config_file = self.save()
                break
            else:
                print(' ... wrong key, try again ...')
            print('')
        if test == 'S':
            print('Configuration has been saved to file "{}"'.format(config_file))

    @property
    def has_materials_project_access(self):
        return self.materials_project_configuration is not None

    def setup_package_options(self):
        self.package_options = self.DEFAULT_PACKAGE_OPTIONS
        print('Choose between the following strategies : ')
        strategies = list(strategies_class_lookup.keys())
        for istrategy, strategy in enumerate(strategies):
            print(' <{}> : {}'.format(str(istrategy + 1), strategy))
        test = input(' ... ')
        self.package_options['default_strategy'] = {'strategy': strategies[int(test) - 1], 'strategy_options': {}}
        strategy_class = strategies_class_lookup[strategies[int(test) - 1]]
        if len(strategy_class.STRATEGY_OPTIONS) > 0:
            for option, option_dict in strategy_class.STRATEGY_OPTIONS.items():
                while True:
                    print('  => Enter value for option "{}" '
                          '(<ENTER> for default = {})\n'.format(option,
                                                                str(option_dict['default'])))
                    print('     Valid options are :\n')
                    print('       {}'.format(option_dict['type'].allowed_values))
                    test = input('     Your choice : ')
                    if test == '':
                        self.package_options['default_strategy']['strategy_options'][option] = option_dict['type'](strategy_class.STRATEGY_OPTIONS[option]['default'])
                        break
                    try:
                        self.package_options['default_strategy']['strategy_options'][option] = option_dict['type'](test)
                        break
                    except ValueError:
                        print('Wrong input for option {}'.format(option))

    def package_options_description(self):
        out = 'Package options :\n'
        out += ' - Maximum distance factor : {:.4f}\n'.format(self.package_options['default_max_distance_factor'])
        out += ' - Default strategy is "{}" :\n'.format(self.package_options['default_strategy']['strategy'])
        strategy_class = strategies_class_lookup[self.package_options['default_strategy']['strategy']]
        out += '{}\n'.format(strategy_class.STRATEGY_DESCRIPTION)
        out += '   with options :\n'
        for option, option_dict in strategy_class.STRATEGY_OPTIONS.items():
            out += '     - {} : {}\n'.format(option,
                                             self.package_options['default_strategy']['strategy_options'][option])
        return out

    def save(self, root_dir=None):
        if root_dir is None:
            home = expanduser("~")
            root_dir = '{}/.chemenv'.format(home)
        if not exists(root_dir):
            makedirs(root_dir)
        config_dict = {'package_options': self.package_options}  
        config_file = '{}/config.json'.format(root_dir)
        if exists(config_file):
            test = input('Overwrite existing configuration ? (<Y> + <ENTER> to confirm)')
            if test != 'Y':
                print('Configuration not saved')
                return config_file
        f = open(config_file, 'w')
        json.dump(config_dict, f)
        f.close()
        print('Configuration saved')
        return config_file

    @classmethod
    def auto_load(cls, root_dir=None):
        if root_dir is None:
            home = expanduser("~")
            root_dir = '{}/.chemenv'.format(home)
        config_file = '{}/config.json'.format(root_dir)
        try:
            f = open(config_file, 'r')
            config_dict = json.load(f)
            f.close()
            return ChemEnvConfig(package_options=config_dict['package_options']) 
            
        except IOError:
            print('Unable to load configuration from file "{}" ...'.format(config_file))
            print(' ... loading default configuration')
            return ChemEnvConfig()
