# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

"""
user preferences
"""

__all__ = ('PreferencesReadError', 'Preferences')

import json
import mozfile
import os
import re
import tokenize
from ConfigParser import SafeConfigParser as ConfigParser
from StringIO import StringIO

class PreferencesReadError(Exception):
    """read error for prefrences files"""


class Preferences(object):
    """assembly of preferences from various sources"""

    def __init__(self, prefs=None):
        self._prefs = []
        if prefs:
            self.add(prefs)

    def add(self, prefs, cast=False):
        """
        :param prefs:
        :param cast: whether to cast strings to value, e.g. '1' -> 1
        """
        # wants a list of 2-tuples
        if isinstance(prefs, dict):
            prefs = prefs.items()
        if cast:
            prefs = [(i, self.cast(j)) for i, j in prefs]
        self._prefs += prefs

    def add_file(self, path):
        """a preferences from a file

        :param path:
        """
        self.add(self.read(path))

    def __call__(self):
        return self._prefs

    @classmethod
    def cast(cls, value):
        """
        interpolate a preference from a string
        from the command line or from e.g. an .ini file, there is no good way to denote
        what type the preference value is, as natively it is a string

        - integers will get cast to integers
        - true/false will get cast to True/False
        - anything enclosed in single quotes will be treated as a string with the ''s removed from both sides
        """

        if not isinstance(value, basestring):
            return value # no op
        quote = "'"
        if value == 'true':
            return  True
        if value == 'false':
            return False
        try:
            return int(value)
        except ValueError:
            pass
        if value.startswith(quote) and value.endswith(quote):
            value = value[1:-1]
        return value


    @classmethod
    def read(cls, path):
        """read preferences from a file"""

        section = None # for .ini files
        basename = os.path.basename(path)
        if ':' in basename:
            # section of INI file
            path, section = path.rsplit(':', 1)

        if not os.path.exists(path) and not mozfile.is_url(path):
            raise PreferencesReadError("'%s' does not exist" % path)

        if section:
            try:
                return cls.read_ini(path, section)
            except PreferencesReadError:
                raise
            except Exception, e:
                raise PreferencesReadError(str(e))

        # try both JSON and .ini format
        try:
            return cls.read_json(path)
        except Exception, e:
            try:
                return cls.read_ini(path)
            except Exception, f:
                for exception in e, f:
                    if isinstance(exception, PreferencesReadError):
                        raise exception
                raise PreferencesReadError("Could not recognize format of %s" % path)


    @classmethod
    def read_ini(cls, path, section=None):
        """read preferences from an .ini file"""

        parser = ConfigParser()
        parser.optionxform = str
        parser.readfp(mozfile.load(path))

        if section:
            if section not in parser.sections():
                raise PreferencesReadError("No section '%s' in %s" % (section, path))
            retval = parser.items(section, raw=True)
        else:
            retval = parser.defaults().items()

        # cast the preferences since .ini is just strings
        return [(i, cls.cast(j)) for i, j in retval]

    @classmethod
    def read_json(cls, path):
        """read preferences from a JSON blob"""

        prefs = json.loads(mozfile.load(path).read())

        if type(prefs) not in [list, dict]:
            raise PreferencesReadError("Malformed preferences: %s" % path)
        if isinstance(prefs, list):
            if [i for i in prefs if type(i) != list or len(i) != 2]:
                raise PreferencesReadError("Malformed preferences: %s" % path)
            values = [i[1] for i in prefs]
        elif isinstance(prefs, dict):
            values = prefs.values()
        else:
            raise PreferencesReadError("Malformed preferences: %s" % path)
        types = (bool, basestring, int)
        if [i for i in values
            if not [isinstance(i, j) for j in types]]:
            raise PreferencesReadError("Only bool, string, and int values allowed")
        return prefs

    @classmethod
    def read_prefs(cls, path, pref_setter='user_pref', interpolation=None):
        """
        Read preferences from (e.g.) prefs.js

        :param path: The path to the preference file to read.
        :param pref_setter: The name of the function used to set preferences
                            in the preference file.
        :param interpolation: If provided, a dict that will be passed
                              to str.format to interpolate preference values.
        """

        marker = '##//' # magical marker
        lines = [i.strip() for i in mozfile.load(path).readlines() if i.strip()]
        _lines = []
        for line in lines:
            if line.startswith(('#', '//')):
                continue
            if '//' in line:
                line = line.replace('//', marker)
            _lines.append(line)
        string = '\n'.join(_lines)

        # skip trailing comments
        processed_tokens = []
        f_obj = StringIO(string)
        for token in tokenize.generate_tokens(f_obj.readline):
            if token[0] == tokenize.COMMENT:
                continue
            processed_tokens.append(token[:2]) # [:2] gets around http://bugs.python.org/issue9974
        string = tokenize.untokenize(processed_tokens)

        retval = []
        def pref(a, b):
            if interpolation and isinstance(b, basestring):
                b = b.format(**interpolation)
            retval.append((a, b))
        lines = [i.strip().rstrip(';') for i in string.split('\n') if i.strip()]

        _globals = {'retval': retval, 'true': True, 'false': False}
        _globals[pref_setter] = pref
        for line in lines:
            try:
                eval(line, _globals, {})
            except SyntaxError:
                print line
                raise

        # de-magic the marker
        for index, (key, value) in enumerate(retval):
            if isinstance(value, basestring) and marker in value:
                retval[index] = (key, value.replace(marker, '//'))

        return retval

    @classmethod
    def write(cls, _file, prefs, pref_string='user_pref(%s, %s);'):
        """write preferences to a file"""

        if isinstance(_file, basestring):
            f = file(_file, 'a')
        else:
            f = _file

        if isinstance(prefs, dict):
            # order doesn't matter
            prefs = prefs.items()

        # serialize -> JSON
        _prefs = [(json.dumps(k), json.dumps(v) )
                  for k, v in prefs]

        # write the preferences
        for _pref in _prefs:
            print >> f, pref_string % _pref

        # close the file if opened internally
        if isinstance(_file, basestring):
            f.close()
