import os

from Ft.Server.Common import ResourceTypes
from Ft.Server.Common.Install import Serialize, InstallUtil

from Server.Server.SCore import test_helper
import test_uptodate

import Server
BASE_DIR = os.path.join(os.path.dirname(Server.__file__), 'Common', 'Install')

def test_resolve(tester, pl):

    tester.startGroup("Resolve base directory")
    pl.setBase('/test')

    for r in pl.resourceList:
        tester.startTest(r.path)
        tester.compare('/test/', r.path[:6])
        if r.resourceType in ResourceTypes.XML_DOCUMENTS and r.docDef is not None:
            tester.compare('/test/', r.docDef[:6])
        if r.resourceType == ResourceTypes.ResourceType.ALIAS:
            if r.path != '/test/test2.alias':
                tester.compare('/test/', r.reference[:6])
            else:
                tester.compare('/ftss/users', r.reference)
        if r.resourceType in [ResourceTypes.ResourceType.USER, ResourceTypes.ResourceType.GROUP]:
            tester.compare('/test/', r.basePath[:6])

        tester.testDone()

    tester.groupDone()

def test_filter(tester, pl):

    test_uptodate.clearCache()
    tester.startTest("Filter the list")
    repo = test_helper.GetRepo(tester)
    pl.filter(repo)
    repo.txRollback()
    tester.testDone()


    tester.startTest("To be installed")
    tester.compare(1, len(pl.filteredList))  #The raw file already present but that needs to be changed
    tester.compare('/test/test2.html', pl.filteredList[0].path)
    tester.compare(len(pl.resourceList)-2, len(pl.sortedList))  #Things to be added, should be t less then the number of resources.  There is a RF that is in the filtered list, and a RF not added

    tester.testDone()

def test_dependencies(tester, pl):

    tester.startGroup("Resource Dependencies")

    for index, dependList in [(0, ['/test/cont']),
                             (1, []),
                             (2, []),
                             (3, []),
                             (4, ['test-user', '/test/perm']),
                             (5, ['/test/perm']),
                             (6, ['/test/perm']),
                             (7, ['/test/test1.xpathdd']),
                             (8, []),
                             (9, ['/test/test1.aliasref']),
                             (10, []),
                             (11, ['/test/test1.xslt']),
                             (12, ['/test/test1.xslt']),
                             (13, []),
                             ]:
        r = pl.sortedList[index]
        tester.startTest(r.path)
        r._gatherDependencies('/test')
        tester.compare(len(dependList), len(r.dependencies))
        for d in r.dependencies:
            tester.compareIn(dependList, d)
        tester.testDone()

    tester.groupDone()

def test_sort(tester, pl):

    class DummyRepo:
        def hasResource(self, path):
            return path == '/ftss/users'
    tester.startGroup("Sort Dependencies")

    tester.startTest('Sortem')
    pl.sort(DummyRepo())
    tester.testDone()

    expected = {0:'/test/cont',
                1:'/test/test3.html',
                2:'/test/perm',
                3:'/test/perm/test-user',
                4:'/test/perm/test-user2',
                5:'/test/test1.xpathdd',
                6:'/test/test1.aliasref',
                7:'/test/test1.xslt',
                8:'/test/test2.alias',
                9:'/test/cont/sub',
                10:'/test/perm/test-group',
                11:'/test/test1.xml',
                12:'/test/test1.alias',
                13:'/test/test-include.xslt',
                14:'/test/test-import.xslt',
                }

    keys = expected.keys()
    keys.sort()
    for index in keys:
        path = expected[index]
        tester.startTest("Entry %d: %s" % (index, path))
        tester.compare(path, pl.sortedList[index].path)
        tester.testDone()
    tester.groupDone()


def test_install(tester):

    tester.startTest("Perform Install")
    repo = test_helper.GetRepo(tester)
    f = open('Server/Common/Install/complex.xml')
    pl = Serialize.Deserialize(f, refUri = 'Server/Common/Install/')
    f.close()
    pl.install(repo, '/test', 0)
    repo.txCommit()
    tester.testDone()

    tester.startGroup("Validate the Install")

    repo = test_helper.GetRepo(tester)

    sources = {}
    for filename in ('test1.html', 'test1.xml', 'test1.xpathdd',
                     'test-include.xslt', 'test-import.xslt', 'test1.xslt'):
        f = open(os.path.join(BASE_DIR, filename), 'rb')
        sources[filename] = f.read()
        f.close()

    for (path, rt, imt, acl, other) in [('/test/cont/sub', ResourceTypes.ResourceType.CONTAINER, 'text/xml', [], {}),
                                    ('/test/cont', ResourceTypes.ResourceType.CONTAINER, 'text/xml', [], {}),
                                    ('/test/test1.html',
                                     ResourceTypes.ResourceType.RAW_FILE,
                                     'text/html',
                                     [],
                                     {'SRC': sources['test1.html']}
                                      ),
                                    ('/test/test2.html',
                                     ResourceTypes.ResourceType.RAW_FILE,
                                     'text/text',
                                     [],
                                     {'SRC': sources['test1.html']}
                                      ),
                                    ('/test/test3.html',
                                     ResourceTypes.ResourceType.RAW_FILE,
                                     'text/plain',
                                     [],
                                     {'SRC': sources['test1.html']}
                                      ),
                                    ('/test/perm',
                                     ResourceTypes.ResourceType.CONTAINER,
                                     'text/xml',
                                     [('read', 'test-user', 1), ('read', 'test-group', 1)],
                                     {'OWNER':'test-user2'},
                                     ),
                                    ('/test/perm/test-group',
                                     ResourceTypes.ResourceType.GROUP,
                                     'text/xml',
                                     [],
                                     {'MEMBERS':['test-user']},
                                     ),
                                    ('/test/perm/test-user',
                                     ResourceTypes.ResourceType.USER,
                                     'text/xml',
                                     [],
                                     {},
                                     ),
                                    ('/test/perm/test-user2',
                                     ResourceTypes.ResourceType.USER,
                                     'text/xml',
                                     [],
                                     {},
                                     ),
                                    ('/test/test1.xml',
                                     ResourceTypes.ResourceType.XML_DOCUMENT,
                                     'text/xml',
                                     [],
                                     {'SRC': sources['test1.xml'],
                                      'DOCDEF':'/test/test1.xpathdd'}
                                      ),
                                    ('/test/test1.xpathdd',
                                     ResourceTypes.ResourceType.XPATH_DOCUMENT_DEFINITION,
                                     'text/xml',
                                     [],
                                     {'SRC': sources['test1.xpathdd'],
                                      }
                                      ),
                                    ('/test/test1.alias',
                                     ResourceTypes.ResourceType.ALIAS,
                                     'text/xml',
                                     [],
                                     {'REF':'/test/test1.aliasref',
                                      }
                                      ),
                                    ('/test/test1.aliasref',
                                     ResourceTypes.ResourceType.RAW_FILE,
                                     'text/plain',
                                     [],
                                     {'SRC': sources['test1.html']}
                                      ),
                                    ('/test/test-include.xslt',
                                     ResourceTypes.ResourceType.XSLT_DOCUMENT,
                                     'text/xml',
                                     [],
                                     {'SRC': sources['test-include.xslt'],
                                      }
                                      ),
                                    ('/test/test-import.xslt',
                                     ResourceTypes.ResourceType.XSLT_DOCUMENT,
                                     'text/xml',
                                     [],
                                     {'SRC': sources['test-import.xslt'],
                                      }
                                      ),
                                    ('/test/test1.xslt',
                                     ResourceTypes.ResourceType.XSLT_DOCUMENT,
                                     'text/xml',
                                     [],
                                     {'SRC': sources['test1.xslt'],
                                      }
                                      ),
                                    ('/test/test2.alias',
                                     ResourceTypes.ResourceType.ALIAS,
                                     'text/xml',
                                     [],
                                     {'REF':'/ftss/users',
                                      }
                                      ),
                                    ]:
        tester.startTest(path)
        tester.compare(1, repo.hasResource(path) > 0)
        res = repo.fetchResource(path + ';no-traverse')
        tester.compare(rt, res.resourceType)
        tester.compare(imt, res.getImt())
        cur = res.getAcl()
        for access, ident, allowed in acl:
            tester.compare(1, cur.has_key(access))
            tester.compare(1, cur[access].has_key(ident))
            tester.compare(allowed, cur[access][ident])


        for name, value in other.items():
            if name == 'SRC':
                tester.compare(value, res.getContent())
            elif name == 'OWNER':
                tester.compare(value, res.getOwner().getUsername())
            elif name == 'MEMBERS':
                for m in res.getMembers():
                    tester.compareIn(value, m.getUsername())
            elif name == 'DOCDEF':
                tester.compare(value, res.getDocumentDefinition().getAbsolutePath())
            elif name == 'REF':
                tester.compare(value, res.getReference().getAbsolutePath())

        tester.testDone()
    repo.txCommit()


    tester.groupDone()




def init(tester):

    tester.startTest("Init")
    repo = test_helper.GetRepo(tester)

    if repo.hasResource('/test'):
        repo.deleteResource('/test')

    repo.createContainer('/test')
    f = open(os.path.join(BASE_DIR, 'test1.html'), 'rb')
    src = f.read()
    f.close()
    repo.createRawFile('/test/test1.html', 'text/html', src)
    repo.createRawFile('/test/test2.html', 'text/html', src)
    repo.txCommit()
    tester.testDone()


def Test(tester):

    init(tester)

    tester.startTest("Load product")
    f = open('Server/Common/Install/complex.xml')
    pl = Serialize.Deserialize(f, refUri = 'Server/Common/Install/')
    f.close()
    tester.testDone()

    test_resolve(tester, pl)
    test_filter(tester, pl)
    test_dependencies(tester, pl)
    test_sort(tester, pl)

    test_install(tester)
