import glob
import os

from django.core.management.base import BaseCommand
from django.db.models import get_apps

from eulcore.django.fedora import Repository
from eulcore.fedora import DigitalObject
from eulcore.fedora.models import ContentModel
from eulcore.fedora.util import RequestFailed

class Command(BaseCommand):
    help = """Generate missing Fedora content model objects and load initial objects."""

    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        self.repo = Repository()

    def handle(self, *args, **options):
        self.verbosity = int(options.get('verbosity', 1))

        # FIXME/TODO: add count/summary info for content models objects created ?
        if self.verbosity > 1:
            print "Generating content models for %d classes" % len(DigitalObject.defined_types)
        for cls in DigitalObject.defined_types.itervalues():
            self.process_class(cls)
            
        self.load_initial_objects()
            
    def process_class(self, cls):
        try:
            ContentModel.for_class(cls, self.repo)
        except ValueError, v:
            # for_class raises a ValueError when a class has >1
            # CONTENT_MODELS.
            if self.verbosity > 1:
                print v

    def load_initial_objects(self):
        # look for any .xml files in apps under fixtures/initial_objects
        # and attempt to load them as Fedora objects

        app_module_paths =  []
        # monkey see django code, monkey do
        for app in get_apps():
            if hasattr(app, '__path__'):
                # It's a 'models/' subpackage
                for path in app.__path__:
                    app_module_paths.append(path)
            else:
                # It's a models.py module
                app_module_paths.append(app.__file__)

        app_fixture_paths = [os.path.join(os.path.dirname(path), 
                                            'fixtures', 'initial_objects', '*.xml')
                                            for  path in app_module_paths]
        fixture_count = 0
        load_count = 0
        
        for path in app_fixture_paths:
            fixtures = glob.iglob(path)
            for f in fixtures:
                # FIXME: is there a sane, sensible way to shorten file path for error/success messages?
                fixture_count += 1
                with open(f) as fixture_data:
                    # rather than pulling PID from fixture and checking if it already exists,
                    # just ingest and catch appropriate excetions
                    try:
                        pid = self.repo.ingest(fixture_data.read(), "loaded from fixture")
                        if self.verbosity > 1:
                            print "Loaded fixture %s as %s" % (f, pid)
                        load_count += 1
                    except RequestFailed, rf:
                        if 'ObjectExistsException' in rf.detail:
                            if self.verbosity > 1:
                                print "Fixture %s has already been loaded" % f
                        elif 'ObjectValidityException' in rf.detail:
                            # could also look for: fedora.server.errors.ValidationException
                            # (e.g., RELS-EXT about does not match pid)
                            print "Error: fixture %s is not a valid Repository object" % f
                        elif hasattr(rf, 'detail'):
                            # if there is at least a detail message, display that
                            print "Error ingesting %s: %s" % (f, rf.detail)
                        else:
                            raise rf

        # summarize what was actually done
        if self.verbosity > 0:
            if fixture_count == 0:
                print "No fixtures found"
            else:
                print "Loaded %d object(s) from %d fixture(s)" % (load_count, fixture_count)

@@ -1446,16 +1446,156 @@
 objects%0A
+        # NOTE! any fixtures should have pids specified, or new versions of the%0A        # fixture will be created every time syncrepo runs%0A%0A
 %0A       
@@ -3045,16 +3045,70 @@
 ed, rf:%0A
+                        if hasattr(rf, 'detail'):%0A    
         
@@ -3184,32 +3184,36 @@
                 
+  
+  
 if self.verbosit
@@ -3211,32 +3211,36 @@
 .verbosity %3E 1:%0A
+    
                 
@@ -3322,24 +3322,28 @@
             
+    
 elif 'Object
@@ -3367,32 +3367,36 @@
 ' in rf.detail:%0A
+    
                 
@@ -3499,16 +3499,20 @@
         
+    
 # (e.g.,
@@ -3543,24 +3543,28 @@
  match pid)%0A
+    
             
@@ -3670,36 +3670,22 @@
     
-elif hasattr(rf, 'detail'):%0A
+    else:%0A    
     
@@ -3762,16 +3762,20 @@
 ay that%0A
+    
         

clean up syncrepo error handling