import logging
import os
import pkg_resources
import unittest

from pyprint.ConsolePrinter import ConsolePrinter

from testfixtures import LogCapture

from coalib.bearlib.aspects import AspectList, get as get_aspect
from coalib.bears.BEAR_KIND import BEAR_KIND
from coalib.bears.Bear import Bear
from coalib.collecting.Collectors import (
    collect_all_bears_from_sections, collect_bears, collect_dirs, collect_files,
    collect_registered_bears_dirs, filter_section_bears_by_languages,
    get_all_bears, get_all_bears_names, collect_bears_by_aspects)
from coalib.output.printers.LogPrinter import LogPrinter
from coalib.output.printers.ListLogPrinter import ListLogPrinter
from coalib.settings.Section import Section
from tests.TestUtilities import bear_test_module


class CollectFilesTest(unittest.TestCase):

    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.collectors_test_dir = os.path.join(current_dir,
                                                'collectors_test_dir')
        self.log_printer = ListLogPrinter()

    def test_file_empty(self):
        self.assertRaises(TypeError, collect_files)

    def test_file_invalid(self):
        with LogCapture() as capture:
            self.assertEqual(collect_files(file_paths=['invalid_path'],
                                           log_printer=self.log_printer,
                                           ignored_file_paths=None,
                                           limit_file_paths=None,
                                           section_name='section'), [])
        capture.check(
            ('root', 'WARNING', 'No files matching \'invalid_path\' were '
                                'found. If this rule is not required, you can '
                                'remove it from section [section] in your '
                                '.coafile to deactivate this warning.')
        )

    def test_file_collection(self):
        self.assertEqual(collect_files([os.path.join(self.collectors_test_dir,
                                                     'others',
                                                     '*',
                                                     '*2.py')],
                                       self.log_printer),
                         [os.path.normcase(os.path.join(
                             self.collectors_test_dir,
                             'others',
                             'py_files',
                             'file2.py'))])

    def test_file_string_collection(self):
        self.assertEqual(collect_files(os.path.join(self.collectors_test_dir,
                                                    'others',
                                                    '*',
                                                    '*2.py'),
                                       self.log_printer),
                         [os.path.normcase(os.path.join(
                             self.collectors_test_dir,
                             'others',
                             'py_files',
                             'file2.py'))])

    def test_ignored(self):
        self.assertEqual(collect_files([os.path.join(self.collectors_test_dir,
                                                     'others',
                                                     '*',
                                                     '*2.py'),
                                        os.path.join(self.collectors_test_dir,
                                                     'others',
                                                     '*',
                                                     '*2.py')],
                                       self.log_printer,
                                       ignored_file_paths=[os.path.join(
                                           self.collectors_test_dir,
                                           'others',
                                           'py_files',
                                           'file2.py')]),
                         [])

    def test_limited(self):
        self.assertEqual(
            collect_files([os.path.join(self.collectors_test_dir,
                                        'others',
                                        '*',
                                        '*py')],
                          self.log_printer,
                          limit_file_paths=[os.path.join(
                                                self.collectors_test_dir,
                                                'others',
                                                '*',
                                                '*2.py')]),
            [os.path.normcase(os.path.join(self.collectors_test_dir,
                                           'others',
                                           'py_files',
                                           'file2.py'))])


class CollectDirsTest(unittest.TestCase):

    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.collectors_test_dir = os.path.join(current_dir,
                                                'collectors_test_dir')

    def test_dir_empty(self):
        self.assertRaises(TypeError, collect_dirs)

    def test_dir_invalid(self):
        self.assertEqual(collect_dirs(['invalid_path']), [])

    def test_dir_collection(self):
        self.assertEqual(
            sorted(i for i in
                   collect_dirs([os.path.join(self.collectors_test_dir,
                                              '**')])
                   if '__pycache__' not in i),
            sorted([os.path.normcase(os.path.join(
                self.collectors_test_dir, 'bears')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'bears_local_global')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'others')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'others',
                                              'c_files')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'others',
                                              'py_files')),
                os.path.normcase(self.collectors_test_dir)]))

    def test_dir_string_collection(self):
        self.assertEqual(
            sorted(i for i in
                   collect_dirs(os.path.join(self.collectors_test_dir,
                                             '**'))
                   if '__pycache__' not in i),
            sorted([os.path.normcase(os.path.join(
                self.collectors_test_dir, 'bears')),
                os.path.normcase(o
s.path.join(self.collectors_test_dir,
                                              'bears_local_global')),
                os.path.normcase(os.path.join(self.coll
ectors_test_dir,
                                              'others')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'others',
                                              'c_files')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                              'others',
                                              'py_files')),
                os.path.normcase(self.collectors_test_dir)]))

    def test_ignored(self):
        self.assertEqual(
            sorted(i for i in
                   collect_dirs([os.path.join(self.collectors_test_dir,
                                              '**')],
                                [os.path.normcase(os.path.join(
                                    self.collectors_test_dir,
                                    'others',
                                    'py_files'))])
                   if '__pycache__' not in i),

            sorted([os.path.normcase(os.path.join(
                self.collectors_test_dir, 'bears')),
                os.path.normcase(os.path.join(self.collectors_test_dir,
                                            