import os
import pytest
import bids
from bids.layout.models import BIDSFile, Entity, Tag, Base, Config, Scope
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker


@pytest.fixture(scope="module")
def session():
    engine = create_engine('sqlite://')
    Base.metadata.create_all(engine)
    Session = sessionmaker(bind=engine)
    return Session()

@pytest.fixture
def sample_bidsfile(tmpdir):
    testfile = 'sub-03_ses-2_task-rest_acq-fullbrain_run-2_bold.nii.gz'
    fn = tmpdir.mkdir("tmp").join(testfile)
    fn.write('###')
    return BIDSFile(os.path.join(str(fn)))


@pytest.fixture(scope='module')
def subject_entity():
    return Entity('subject', r"[/\\\\]sub-([a-zA-Z0-9]+)", mandatory=False,
               directory="{subject}", dtype='str')


def test_entity_initialization():
    e = Entity('avaricious', r'aardvark-(\d+)')
    assert e.name == 'avaricious'
    assert e.pattern == r'aardvark-(\d+)'
    assert not e.mandatory
    assert e.directory is None
    assert e.files == {}


def test_entity_init_all_args(subject_entity):
    ent = subject_entity
    assert ent.name == 'subject'
    assert ent.pattern == "[/\\\\]sub-([a-zA-Z0-9]+)"
    assert ent.mandatory == False
    assert ent.directory == "{subject}"
    assert ent.map_func is None
    assert ent.kwargs == {'bleargh': True}


def test_entity_init_with_bad_dtype():
    with pytest.raises(ValueError) as exc:
        ent = Entity('test', dtype='superfloat')
        msg = exc.value.message
        assert msg.startswith("Invalid dtype")


def test_entity_deepcopy(subject_entity):
    e = subject_entity
    clone = copy.deepcopy(subject_entity)
    for attr in ['name', 'pattern', 'mandatory', 'directory', 'map_func',
                 'regex', 'kwargs']:
        assert getattr(e, attr) == getattr(clone, attr)
    assert e != clone


def test_entity_matches(tmpdir):
    filename = "aardvark-4-reporting-for-duty.txt"
    tmpdir.mkdir("tmp").join(filename).write("###")
    f = BIDSFile(os.path.join(str(tmpdir), filename))
    e = Entity('avaricious', r'aardvark-(\d+)')
    result = e.match_file(f)
    assert result == '4'


def test_entity_matches_with_map_func(sample_bidsfile):
    bf = sample_bidsfile
    e = Entity('test', map_func=lambda x: x.filename.split('-')[1])
    assert e.match_file(bf) == '03_ses'


def test_entity_unique_and_count():
    e = Entity('prop', r'-(\d+)')
    e.files = {
        'test1-10.txt': '10',
        'test2-7.txt': '7',
        'test3-7.txt': '7'
    }
    assert sorted(e.unique()) == ['10', '7']
    assert e.count() == 2
    assert e.count(files=True) == 3


def test_tag_dtype(sample_bidsfile, subject_entity):
    f, e = sample_bidsfile, subject_entity
    # Various ways of initializing--should all give same result
    tags = [
        Tag(f, e, 4, int),
        Tag(f, e, '4', 'int'),
        Tag(f, e, '4', int),
        Tag(f, e, 4),
        Tag(file=f, entity=e, dtype=int, value='4')
    ]
    assert all([t.dtype == int for t in tags])


def test_entity_add_file(sample_bidsfile, session):
    bf = sample_bidsfile
    e = Entity('prop', r'-(\d+)')
    t = Tag(file=bf, entity=e, value=4)
    session.add(t)
    session.commit()
    print(e.files)
    print(bf.entities)
    assert e.files[bf.path] == '4'


def test_config_init_with_args():
    ents = [
        {
            "name": "task",
            "pattern": "[_/\\\\]task-([a-zA-Z0-9]+)"
        },
        {
            "name": "acquisition",
            "pattern": "[_/\\\\]acq-([a-zA-Z0-9]+)"
        }
    ]
    patterns = ['this_will_never_match_anything', 'and_neither_will_this']
    config = Config('custom', entities=ents, default_path_patterns=patterns)
    assert config.name == 'custom'
    assert [ent.name for ent in config.entities] == ['task', 'acquisition']
    assert config.default_path_patterns  == patterns


def test_scope_init():
    scope = Scope(name='bids', path='/tmp')
    assert scope.name == 'bids'
    assert scope.path == '/tmp'
@@ -103,16 +103,51 @@
 , Scope%0A
+from bids.layout import BIDSLayout%0A
 from sql
@@ -221,44 +221,19 @@
 r%0A%0A%0A
-@pytest.fixture(scope=%22module%22)%0Adef 
+def create_
 sess
@@ -364,24 +364,96 @@
     
-return Session()
+from bids.layout import layout%0A    layout.session = Session()%0A    return layout.session%0A
 %0A%0A@p
@@ -1233,16 +1233,17 @@
 tern == 
+r
 %22%5B/%5C%5C%5C%5C%5D
@@ -1340,83 +1340,8 @@
 t%7D%22%0A
-    assert ent.map_func is None%0A    assert ent.kwargs == %7B'bleargh': True%7D%0A
 %0A%0Ade
@@ -1546,24 +1546,26 @@
 d dtype%22)%0A%0A%0A
+# 
 def test_ent
@@ -1590,24 +1590,26 @@
 ct_entity):%0A
+# 
     e = subj
@@ -1615,24 +1615,26 @@
 ject_entity%0A
+# 
     clone = 
@@ -1663,20 +1663,22 @@
 entity)%0A
+#
     
+ 
 for attr
@@ -1730,21 +1730,11 @@
 ry',
- 'map_func',%0A
+%0A# 
     
@@ -1766,16 +1766,18 @@
 args'%5D:%0A
+# 
         
@@ -1824,16 +1824,18 @@
 , attr)%0A
+# 
     asse
@@ -2148,199 +2148,8 @@
 '%0A%0A%0A
-def test_entity_matches_with_map_func(sample_bidsfile):%0A    bf = sample_bidsfile%0A    e = Entity('test', map_func=lambda x: x.filename.split('-')%5B1%5D)%0A    assert e.match_file(bf) == '03_ses'%0A%0A%0A
 def 
@@ -2766,24 +2766,59 @@
 ='4')%0A    %5D%0A
+    print(%5Bt.dtype for t in tags%5D)%0A
     assert a
@@ -3154,24 +3154,55 @@
 ith_args():%0A
+    session = create_session()%0A
     ents = %5B
@@ -3651,16 +3651,25 @@
 entities
+.values()
 %5D == %5B't

fix model tests