# -*- coding: utf-8 -*-
r"""Read INI-style configuration files.

"""

from __future__ import division, absolute_import, print_function

import sys
import os
import io
import locale
try:
    from configparser import SafeConfigParser, NoSectionError, NoOptionError
except ImportError:
    from ConfigParser import SafeConfigParser, NoSectionError, NoOptionError

from .compat import PY2


__all__ = ["INIConfigParser", "NoSectionError", "NoOptionError"]


class INIConfigParser(SafeConfigParser):

    """A case sensitive config parser that returns all-unicode string
    values.

    """

    def __init__(self, filename, executable=None, encoding=None):
        SafeConfigParser.__init__(self)
        if executable is None:
            executable = sys.argv[0]
        if PY2:
            if isinstance(filename, str):
                filename = filename.decode(locale.getpreferredencoding())
            if isinstance(executable, str):
                executable = executable.decode(locale.getpreferredencoding())
        self.executable = os.path.normpath(os.path.abspath(executable))
        if encoding is None:
            encoding = locale.getpreferredencoding()
        self.encoding = encoding
        with io.open(filename, mode="rt", encoding=self.encoding) as cf:
            self.readfp(cf, filename)

    def optionxform(self, option):
        return option

    def get_path_list(self, section, option):
        v = self.get(section, option)
        return v.split(os.pathsep)

    def read(self, filenames):
        raise NotImplementedError("use `readfp()' instead")

    def readfp(self, fp, filename):
        if hasattr(self, "filename"):
            raise RuntimeError("already initialized")
        filename = os.path.normpath(os.path.abspath(filename))
        if PY2:
            if isinstance(filename, str):
                filename = filename.decode(locale.getpreferredencoding())
        self.set(None, "self", filename)
        self.set(None, "here", os.path.dirname(filename))
        self.set(None, "root", os.path.dirname(self.executable))
        SafeConfigParser.readfp(self, fp, filename=filename)
        self.filename = filename
        self.root = os.path.dirname(self.executable)

    def getx(self, section, option):
        """Extended get() with some automatic type conversion support.

        Default: Fetch as string (like `get()`).

        If annotated with ``:bool:`` fetch as bool, if annotated with
        ``:int:`` fetch as int, if annotated with ``:float:`` fetch as
        float.

        """
        v = self.get(section, option)
        if v.startswith(":bool:"):
            v = v[6:].lower()
            if v not in self._BOOL_CVT:
                raise ValueError("Not a boolean: %s" % (v, ))
            return self._BOOL_CVT[v]
        elif v.startswith(":int:"):
            return int(v[5:], 0)
        elif v.startswith(":float:"):
            return float(v[7:])
        else:
            return v

    _BOOL_CVT = {'1': True, 'yes': True, 'true': True, 'on': True,
                 '0': False, 'no': False, 'false': False, 'off': False}
