# -*- coding: utf-8 -*-
#
# ccwatcher (http://ccwatcher.sourceforge.net/)
# Copyright (C) 2009-2013 Xaver Wurzenberger <xaverxn at users.sourceforge.net>
#
# This program is free software; you can redistribute and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.

"""ccw_settingshandler.py
"""

import ConfigParser #Windows-style ini file in ~/.config/ccwatcher (Linux) or USER\Anwendungsdaten\ccwatcher (German WindowsXP)
import os


def getSettingsFileLocation(): #Remember: Get a check for MacOS too!
    """Tries to get a sensible location for ini file. The exotic cases of multiple files or file locations and writable home/appdata but non-writable (and maybe readable) ini file are not covered"""
    
    if os.getenv("XDG_CONFIG_HOME"): #unix; according to freedesktop.org standarts; returns None if not available
        if not os.path.exists(os.path.join(os.getenv("XDG_CONFIG_HOME"),"ccwatcher")) and os.access(os.getenv("XDG_CONFIG_HOME"), os.W_OK):
            os.mkdir(os.path.join(os.getenv("XDG_CONFIG_HOME"),"ccwatcher"))
        settingsfile = os.path.join(os.getenv("XDG_CONFIG_HOME"),"ccwatcher","ccwatcher.ini")
    elif os.getenv("HOME"): #unix; returns None if HOME not available
        if os.path.exists(os.path.join(os.getenv("HOME"),".config")): #1st fallback (cleaner than just making a .ccwatcher dir)
            if not os.path.exists(os.path.join(os.getenv("HOME"),".config", "ccwatcher")) and os.access(os.path.join(os.getenv("HOME"),".config"), os.W_OK):
                os.mkdir(os.path.join(os.getenv("HOME"),".config", "ccwatcher"))
            settingsfile = os.path.join(os.getenv("HOME"),".config","ccwatcher","ccwatcher.ini")
        elif os.path.exists(os.path.join(os.getenv("HOME"),".ccwatcher")) and os.access(os.path.join(os.getenv("HOME"),".ccwatcher"), os.W_OK):#2nd fallback
            settingsfile = os.path.join(os.getenv("HOME"),".ccwatcher","ccwatcher.ini")
        elif not os.path.exists(os.path.join(os.getenv("HOME"),".ccwatcher")) and os.access(os.getenv("HOME"), os.W_OK): #2nd fallback
            os.mkdir(os.path.join(os.getenv("HOME"),".ccwatcher"))
            settingsfile = os.path.join(os.getenv("HOME"),".ccwatcher","ccwatcher.ini")
    elif os.environ.get('APPDATA',False): #win32
        if not os.path.exists(os.path.join(os.environ['APPDATA'],"ccwatcher")) and os.access(os.environ['APPDATA'], os.W_OK):
            os.mkdir(os.path.join(os.environ['APPDATA'],"ccwatcher"))
        settingsfile = os.path.join(os.environ['APPDATA'],"ccwatcher","ccwatcher.ini")
    elif os.access("ccwatcher.ini", os.W_OK):
        settingsfile = "ccwatcher.ini"
    else:
        settingsfile = None
        print "No (writable) .ini config file location found!  Using built-in defaults..." #No logger so it's import-able
        return settingsfile

    #print "Config file:", settingsfile #dont print this as "writing settings to XX" (from readsettings) is printed often enough
    return os.path.abspath(settingsfile)


def writeSettings(dict_writesettings, settingsfile):
#    """Attention: the given list is changed (NOT ANY MORE!!!), and as a mutable filetype, the original variable is changed. So always give this function a copy() of the data if you want to further use it!"""
#    dict_writesettings['list_keywords_gaussian'] = ",".join(dict_writesettings['list_keywords_gaussian']) #save a string instead of a list. Why, actually?
    if settingsfile:
        configparser = ConfigParser.ConfigParser()
        configparser.add_section('general')
        for key,value in dict_writesettings.items():
                configparser.set('general', key, value)
        out = open(settingsfile,"w")
        configparser.write(out)
        out.close()
        info = "Writing settings to "+settingsfile+"..."
    else:
        print "writeSettings function: No settings file given. Not writing anything."
        
    return info
    

def readSettings(settingsfile):
    """Reads the settingsfile into 'dict_readsettings and merges them with dict_hardcodedsettings (via reverse-'dict.update()). Then strange and possibly obsolete keyword update function and writeback and return"""

    if settingsfile:
        configparser = ConfigParser.ConfigParser()
        configparser.read(settingsfile) #if settingsfile is not existant, this returns an empty list
        dict_readsettings = {}
        if len(configparser.sections()) > 0:
#            for sec in configparser.sections():
#                name=sec.lower()
            for opt in configparser.options('general'):
                    dict_readsettings[opt.lower()] = configparser.get('general', opt).strip() #for several sections maybe: dict_settings[name+"."+string.lower(opt)]=string.strip(configparser.get(sec,opt))

        from ccw_messages import dict_hardcodedsettings
        dict_newsettings = dict_hardcodedsettings.copy()
        if type(dict_readsettings) == dict:
            dict_newsettings.update(dict_readsettings)

        #transformation of the content to sensible data types; unneccessary for strings
        dict_newsettings['num_max_file_age_minutes'] = int(dict_newsettings['num_max_file_age_minutes'])
        dict_newsettings['num_verbosity'] = int(dict_newsettings['num_verbosity'])
        dict_newsettings['use_gui'] = eval(str(dict_newsettings['use_gui']))
        dict_newsettings['no_zero_convergence'] = eval(str(dict_newsettings['no_zero_convergence']))
        dict_newsettings['no_guess_mode'] = eval(str(dict_newsettings['no_guess_mode']))
        dict_newsettings['num_multifile_opt'] = int(dict_newsettings['num_multifile_opt'])
        for item in ("gaussian", "turbomole", "gamess_us", "molpro", "orca", "nwchem", "adf", "adf2012", "jaguar","firefly"):
            if type(dict_newsettings['list_keywords_'+item]) == str:
                 dict_newsettings['list_keywords_'+item] = eval(dict_newsettings['list_keywords_'+item])


        writeSettings(dict_newsettings.copy(), settingsfile) #always write to ini file after read-updating the dict? Might save corrupt inis and help with updating to newer versions of ccwatcher
        return dict_newsettings
        
    else:
        print "readSettings function: No settings file given. Not reading anything."
        return None
