from __future__ import unicode_literals
from __future__ import absolute_import, division, print_function

"""
Annalist test initialization support
"""

__author__      = "Graham Klyne (GK@ACM.ORG)"
__copyright__   = "Copyright 2015, G. Klyne"
__license__     = "MIT (http://opensource.org/licenses/MIT)"

import logging
log = logging.getLogger(__name__)

import os.path
import shutil
import datetime

# from django.test import TestCase
from django.conf import settings

from utils.py3porting               import isoformat_space

from annalist                       import layout
from annalist.util                  import replacetree, removetree
from annalist.collections_data      import installable_collections
from annalist.identifiers           import ANNAL, RDFS

from annalist.models.site           import Site
from annalist.models.collection     import Collection
from annalist.models.annalistuser   import AnnalistUser
from annalist.models.recordtype     import RecordType
from annalist.models.recordview     import RecordView
from annalist.models.recordlist     import RecordList
from annalist.models.recordfield    import RecordField
from annalist.models.recordvocab    import RecordVocab
from annalist.models.recordtypedata import RecordTypeData
from annalist.models.entitydata     import EntityData
from annalist.models.collectiondata import initialize_coll_data, copy_coll_data, migrate_coll_data

from .entity_testutils              import collection_create_values
from .entity_testtypedata           import recordtype_create_values
from .tests import (
    test_layout,
    TestHost, TestHostUri, TestBasePath, TestBaseUri, TestBaseDir
    )

sitedata_target_reset = "all"

def resetSitedata(scope="all"):
    """
    Set flag to reset site and/or collection data at next test initialization

    (This is really just a performance hack to reduce the amount of file copying performed 
    for each test.  Tests should run correctly if all site and collection data is reset for 
    every test, but that causes the tests take much longer to run.)
    """
    global sitedata_target_reset
    if sitedata_target_reset != "all":
        if scope != "collections":
            scope="all"
        sitedata_target_reset = scope
    return

def copySitedata(src, sitedatasrc, tgt):
    """
    Creates a set of Annalist site data by making a copy of a specified
    source tree.

    src         source directory containing site collection test data to be copied
    sitedatasrc source directory containing standard site data to be copied
    tgt         target directory in which the site data is created
    """
    # Confirm existence of target directory
    log.debug("copySitedata: src %s"%(src))
    log.debug("copySitedata: tgt %s"%(tgt))
    assert os.path.exists(src), "Check source directory (%s)"%(src)
    assert os.path.exists(sitedatasrc), "Check site data source directory (%s)"%(sitedatasrc)
    assert tgt.startswith(TestBaseDir)
    # Site data is not updated by the tests, so initialize it just once for each test suite run
    sitedatatgt = os.path.join(tgt, test_layout.SITEDATA_BASE_DIR)
    global sitedata_target_reset
    if sitedata_target_reset == "all":
        replacetree(src, tgt)
        for sdir in layout.COLL_DIRS:
            s = os.path.join(sitedatasrc, sdir)
            d = os.path.join(sitedatatgt, sdir)
            if os.path.isdir(s):
                replacetree(s, d)
    elif sitedata_target_reset == "collections":
        ds = os.path.join(src, "c")
        dt = os.path.join(tgt, "c")
        # Update collections, not site data; first remove old collections
        for coll_id in os.listdir(dt):
            if coll_id != layout.SITEDATA_ID:
                d = os.path.join(dt, coll_id)
                removetree(d)
        for coll_id in os.listdir(ds):
            if coll_id != layout.SITEDATA_ID:
                s = os.path.join(ds, coll_id)
                d = os.path.join(dt, coll_id)
                shutil.copytree(s, d)
    sitedata_target_reset = "none"
    # Confirm existence of target directories
    assert os.path.exists(tgt), "checking target directory created (%s)"%(tgt)
    assert os.path.exists(sitedatatgt), "checking target sitedata directory created (%s)"%(sitedatatgt)
    return tgt

def init_annalist_test_site():
    log.debug("init_annalist_test_site")
    copySitedata(
        settings.SITE_SRC_ROOT+"/sampledata/testinit/"+test_layout.SITE_DIR_NAME, 
        settings.SITE_SRC_ROOT+"/annalist/data/sitedata",
        TestBaseDir)
    testsite = Site(TestBaseUri, TestBaseDir)
    testsite.generate_site_jsonld_context()
    Collection.flush_all_caches()
    # Reset id generator counters
    EntityData._last_id   = 0
    RecordType._last_id   = 0
    RecordView._last_id   = 0
    RecordList._last_id   = 0
    RecordField._last_id  = 0
    RecordVocab._last_id  = 0
    AnnalistUser._last_id = 0