#!/usr/bin/env python
# -*- coding = utf-8 -*-
# filename: utils.py

import io
import os
import sys
import stat
import platform
import configparser

SUFFIX = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
__os_sep__ = "/" if platform.system() == 'Windows' else os.sep


def appromix(size, base=0):
    '''Conver bytes stream size to human-readable format.
    Keyword arguments:
    size: int, bytes stream size
    base: int, suffix index
    Return: string
    '''
    multiples = 1024
    if size < 0:
        raise ValueError('[-] Error: number must be non-negative.')
    if size < multiples:
        return '{0:d}{1}'.format(size, SUFFIX[base])
    for suffix in SUFFIX[base:]:
        if size < multiples:
            return '{0:.2f}{1}'.format(size, suffix)
        size = size / float(multiples)
    raise ValueError('[-] Error: number too big.')


def get_file_ext_name(filename, double_ext=True):
    li = filename.split(os.extsep)
    if len(li) <= 1:
        return ''
    else:
        if li[-1].find(__os_sep__) != -1:
            return ''
    if double_ext:
        if len(li) > 2:
            if li[-2].find(__os_sep__) == -1:
                return '%s.%s' % (li[-2], li[-1])
    return li[-1]


class Fdfs_ConfigParser(configparser.RawConfigParser):
    """ 
    Extends ConfigParser to allow files without sections. 
 
    This is done by wrapping read files and prepending them with a placeholder 
    section, which defaults to '__config__' 
    """

    def __init__(self, default_section=None, *args, **kwargs):
        configparser.RawConfigParser.__init__(self, *args, **kwargs)

        self._default_section = None
        self.set_default_section(default_section or '__config__')

    def get_default_section(self):
        return self._default_section

    def set_default_section(self, section):
        self.add_section(section)

        # move all values from the previous default section to the new one 
        try:
            default_section_items = self.items(self._default_section)
            self.remove_section(self._default_section)
        except configparser.NoSectionError:
            pass
        else:
            for (key, value) in default_section_items:
                self.set(section, key, value)

        self._default_section = section

    def read(self, filenames):
        if isinstance(filenames, str):
            filenames = [filenames]

        read_ok = []
        for filename in filenames:
            try:
                with open(filename) as fp:
                    self.readfp(fp)
            except IOError:
                continue
            else:
                read_ok.append(filename)

        return read_ok

    def readfp(self, fp, *args, **kwargs):
        stream = io.StringIO()

        try:
            stream.name = fp.name
        except AttributeError:
            pass

        stream.write('[' + self._default_section + ']\n')
        stream.write(fp.read())
        stream.seek(0, 0)

        return self._read(stream, stream.name)

    def write(self, fp):
        # Write the items from the default section manually and then remove them 
        # from the data. They'll be re-added later. 
        try:
            default_section_items = self.items(self._default_section)
            self.remove_section(self._default_section)

            for (key, value) in default_section_items:
                fp.write("{0} = {1}\n".format(key, value))

            fp.write("\n")
        except configparser.NoSectionError:
            pass

        configparser.RawConfigParser.write(self, fp)

        self.add_section(self._default_section)
        for (key, value) in default_section_items:
            self.set(self._default_section, key, value)

    def _read(self, fp, fpname):
        """Parse a sectioned setup file.

        The sections in setup file contains a title line at the top,
        indicated by a name in square brackets (`[]'), plus key/value
        options lines, indicated by `name: value' format lines.
        Continuations are represented by an embedded newline then
        leading whitespace.  Blank lines, lines beginning with a '#',
        and just about everything else are ignored.
        """
        cursect = None  # None, or a dictionary
        optname = None
        lineno = 0
        e = None  # None, or an exception
        while True:
            line = fp.readline()
            if not line:
                break
            lineno = lineno + 1
            # comment or blank line?
            if line.strip() == '' or line[0] in '#;':
                continue
            if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
                # no leading whitespace
                continue
            # continuation line?
            if line[0].isspace() and cursect is not None and optname:
                value = line.strip()
                if value:
                    cursect[optname] = "%s\n%s" % (cursect[optname], value)
            # a section header or option header?
            else:
                # is it a section header?
                mo = self.SECTCRE.match(line)
                if mo:
                    sectname = mo.group('header')
                    if sectname in self._sections:
                        cursect = self._sections[sectname]
                    elif sectname == DEFAULTSECT:
                        cursect = self._defaults
                    else:
                        cursect = self._dict()
                        cursect['__name__'] = sectname
                        self._sections[sectname] = cursect
                    # So sections can't start with a continuation line
                    optname = None
                # no section header in the file?
                elif cursect is None:
                    raise MissingSectionHeaderError(fpname, lineno, line)
                # an option line?
                else:
                    mo = self.OPTCRE.match(line)
                    if mo:
                        optname, vi, optval = mo.group('option', 'vi', 'value')
                        if vi in ('=', ':') and ';' in optval:
                            # ';' is a comment delimiter only if it follows
                            # a spacing character
                            pos = optval.find(';')
                            if pos != -1 and optval[pos - 1].isspace():
                                optval = optval[:pos]
                        optval = optval.strip()
                        # allow empty values
                        if optval == '""':
                            optval = ''
                        optname = self.optionxform(optname.rstrip())
                        if optname in cursect:
                            if not isinstance(cursect[optname], list):
                                cursect[optname] = [cursect[optname]]
                            cursect[optname].append(optval)
                        else:
                            cursect[optname] = optval
                    else:
                        # a non-fatal parsing error occurred.  set up the
                        # exception but keep going. the exception will be
                        # raised at the end of the file and will contain a
                        # list of all bogus lines
                        if not e:
                            e = ParsingError(fpname)
                        e.append(lineno, repr(line))
        # if any parsing errors occurred, raise an exception
        if e:
            raise e


def split_remote_fileid(remote_file_id):
    '''
    Splite remote_file_id to (group_name, remote_file_name)
    arguments:
    @remote_file_id: string
    @return tuple, (group_name, remote_file_name)
    '''
    index = remote_file_id.find(b'/')
    if -1 == index:
        return None
    return (remote_file_id[0:index], remote_file_id[(index + 1):])


def fdfs_check_file(filename):
    ret = True
    errmsg = ''
    if not os.path.isfile(filename):
        ret = False
        errmsg = '[-] Error: %s is not a file.' % filename
    elif not stat.S_ISREG(os.stat(filename).st_mode):
        ret = False
        errmsg = '[-] Error: %s is not a regular file.' % filename
    return (ret, errmsg)


if __name__ == '__main__':
    print(get_file_ext_name('/bc.tar.gz'))
