from __future__ import (absolute_import, division, print_function) __metaclass__ = type

import re

from qb import logging

# Constants # ============================================================================

# Regular expression to split strings into their module namespace pieces by # `::` (Ruby) or `.` (Python, Javascript). # NAMESPACE_SPLIT_RE = re.compile(r'(?:::)|.|#')

logger = logging.getLogger('qb.strings')

# Functions # ============================================================================

def words(string):

'''break a string into words

>>> words('git_submodule_update')
['git', 'submodule', 'update']

>>> words("qb.DoSomething")
['qb', 'Do', 'Something']

>>> words("TestGem::SomeClass")
['Test', 'Gem', 'Some', 'Class']

>>> words("MyAPIClass")
['My', 'API', 'Class']

>>> words('ThisIsAName')
['This', 'Is', 'A', 'Name']

>>> words('404Error')
['404', 'Error']

>>> words('MyPackageV1')
['My', 'Package', 'V', '1']

# Don't work with doctest I guess..?
# >>> [print(_) for _ in words(u'中文')]
# [u'中文']
'''

consumers = [
    [tag, [re.compile(pattern, re.U) for pattern in patterns]]
    for tag, patterns in 
    [
        ['break', [r'([\W\_]+)']],
        ['lower_case', [r'([a-z]+)']],
        ['capitalized', [r'([A-Z][a-z]+)']],
        ['acronym', [
            r'([A-Z]+)[A-Z][a-z]',
            r'([A-Z]+)[0-9]',
            r'([A-Z]+)\z',
        ]],
        ['number', [r'([0-9]+)']],
        ['other', [r'([^0-9a-zA-Z]+)']],
    ]
]

def find(remaining):
    for tag, exps in consumers:
        for exp in exps:            
            # print("matching %s %s %s" % (tag, exp, remaining))
            match = exp.match(remaining)
            if match:
                # print("matched %s! %s" % (tag, match.group(0)))
                return [tag, exp, match]
    raise StandardError("bad string: %s" % remaining)

index = 0
results = []
remaining = string

while len(remaining) > 0:
    [tag, exp, match] = find(remaining)
    if tag != 'break':
        results.append(remaining[:match.end(1)])
    remaining = remaining[match.end(1):]

return results

def snake(name):

'''
Turn a name into underscore-separated lower case.

>>> snake('git_submodule_update')
'git_submodule_update'

>>> snake("qb.DoSomething")
'qb_do_something'

>>> snake("TestGem::SomeClass")
'test_gem_some_class'

>>> snake("MyAPIClass")
'my_api_class'

>>> snake('ThisIsAName')
'this_is_a_name'

>>> snake('404Error')
'404_error'

>>> snake('MyPackageV1')
'my_package_v_1'

'''
return '_'.join([part.lower() for part in words(name)])

def name_to_filepath(name):

'''
Turn a 'name' into a file path.

>>> filepath('TestGem::SomeClass')
'test_gem/some_class'

>>> filepath('TestGem::SomeClass#that_method')
'test_gem/some_class/that_method'

# TODO
# >>> filepath("TestGem::SomeClass How to do something")
# 'test_gem/some_class/how_to_do_something'

>>> filepath('qb.strings.filepath')
'qb/strings/filepath'

'''
namespaces = NAMESPACE_SPLIT_RE.split(name)
snaked = [snake(words_) for words_ in namespaces]
joined = "/".join(snaked)
return joined

def filepath(name):

'''
DEPRECIATED - Renamed {.name_to_filepath}
'''

logger.warning(
    "DEPRECIATED - qb.strings.filepath() has been " +
    "renamed qb.strings.name_to_filepath()"
)

return name_to_filepath(name)

def url_to_filepath(url):

'''
Turn a URL string into a filepath.

Useful for making temp / cache / destination paths for downloads.

>>> url_to_filepath('https://ftp.gnu.org/gnu/bash/bash-4.4.18.tar.gz')
'https/ftp.gnu.org/gnu/bash/bash-4.4.18.tar.gz'

'''

return url.replace('://', '/').replace(':', '-')

# testing - call camel_case on first cli arg and print result if __name__ == '__main__':

import doctest
doctest.testmod()