''' -- imports from python libraries -- '''
import os
import time
from sys import argv, exc_info
import json
from datetime import datetime

''' imports from installed packages '''
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from optparse import make_option

# from mongokit import IS

try:
  from bson import ObjectId
except ImportError:  # old pymongo
  from pymongo.objectid import ObjectId

''' imports from application folders/files '''
from gnowsys_ndf.ndf.models import db, node_collection, triple_collection
# from gnowsys_ndf.ndf.models import Node, GSystemType, ToReduceDocs, ReducedDocs, IndexedWordList
# from gnowsys_ndf.ndf.models import Group
# from gnowsys_ndf.ndf.models import DATA_TYPE_CHOICES, QUIZ_TYPE_CHOICES_TU
from gnowsys_ndf.settings import GAPPS
from gnowsys_ndf.settings import META_TYPE
from gnowsys_ndf.settings import GSTUDIO_TASK_TYPES
from gnowsys_ndf.factory_type import factory_gsystem_types, factory_attribute_types, factory_relation_types

###############################################################################
# Global variables

filename = argv[-1]
f = filename.split("/")
if f[-1] == "ATs.json" or f[-1] == "RTs.json" or f[-1] == "STs.json":
  json_file = open(filename)
else:
  json_file = ""

SCHEMA_ROOT = os.path.join( os.path.dirname(__file__), "schema_files")

log_list = [] # To hold intermediate error and information messages
log_list.append("\n######### Script run on : " + time.strftime("%c") + " #########\n############################################################\n")

###############################################################################

class Command(BaseCommand):
  help = "This performs activities required for setting up default structure or updating it." 

  option_list = BaseCommand.option_list

  user_defined_option_list = (
    make_option('-s', '--setup-structure', action='store_true', dest='setup_structure', default=True, help='This performs activities required for setting up default structure or updating it.'),
    make_option('-n', '--no-structure', action='store_false', dest='setup_structure', default=True, help='This skips performing any activities required for updating structure.'),
    make_option('-c', '--clean-structure', action='store_true', dest='clean_structure', default=False, help='This performs activities required for cleaning inconsistent data in structure.'),
  )

  option_list = option_list + user_defined_option_list

  def handle(self, *args, **options):
    if options["setup_structure"]:
      try:
        info_message = "\n Performing structure create/update...\n"
        print info_message
        log_list.append(info_message)

        user_id = 1 
        node_doc = None
        meta_type_name = META_TYPE[0]

        for each in META_TYPE:
          meta_type = node_collection.one({'$and':[{'_type':'MetaType'},{'name':each}]})
          if meta_type == None:                
            create_meta_type(user_id,each)

          else:
            print "Meta_Type",each,"already created"

        meta_type = node_collection.one({'$and':[{'_type':'MetaType'},{'name':meta_type_name}]}) # getting MetaType Object
       
 if meta_type == None:
          meta_type = create_meta_type(user_id) #creating MetaType
        
        for each in GAPPS:
          # Temporarily made this change for renaming "Browse Topic & Browse Resource" untill all servers will be updated
          if each == "Topics":
            br_topic = node_collection.one({'_type':'GSystemType', 'name': 'Browse Topic'})
            if br_
topic:
              br_topic.name = unicode(each)
              br_topic.status = u"PUBLISHED"
              br_topic.save()

          if each == "E-Library":
            br_resource = node_collection.one({'_type':'GSystemType', 'name': 'Browse Resource'})
            if br_resource:
              br_resource.name = unicode(each)
              br_resource.status = u"PUBLISHED"
              br_resource.save()
          # Keep above part untill all servers updated
          
          node_doc = node_collection.one({'$and':[{'_type':'GSystemType'},{'name':each}]})
          if (node_doc == None or each != node_doc['name']):
            gst_node=node_collection.collection.GSystemType()
            gst_node.name = unicode(each)
            gst_node.created_by = user_id
            gst_node.modified_by = user_id

            if user_id not in gst_node.contributors:
              gst_node.contributors.append(user_id)

            gst_node.member_of.append(meta_type._id) # appending metatype to the GSystemType
            gst_node.status = u"PUBLISHED"
            gst_node.save()

          elif(meta_type._id not in node_doc.member_of):
            node_doc.member_of.append(meta_type._id)
            node_doc.status = u"PUBLISHED"
            node_doc.save()
                   
        # Create default group 'home'
        node_doc =node_collection.one({'$and':[{'_type': u'Group'},{'name': u'home'}]})
        if node_doc is None:
          gs_node = node_collection.collection.Group()
          gs_node.name = u'home'
          gs_node.created_by = user_id
          gs_node.modified_by = user_id

          if user_id not in gs_node.contributors:
            gs_node.contributors.append(user_id)

          gs_node.member_of.append(node_collection.one({"_type": "GSystemType", 'name': "Group"})._id)
          gs_node.disclosure_policy=u'DISCLOSED_TO_MEM'
          gs_node.subscription_policy=u'OPEN'
          gs_node.visibility_policy=u'ANNOUNCED'
          gs_node.encryption_policy=u'NOT_ENCRYPTED'
          gs_node.group_type= u'PUBLIC'
          gs_node.edit_policy =u'NON_EDITABLE'
          gs_node.save()
        
        # Creating factory GSystemType's 
        create_sts(factory_gsystem_types,user_id)

        # Creating factory RelationType's 
        create_rts(factory_relation_types,user_id)

        # Creating factory AttributeType's
        create_ats(factory_attribute_types,user_id)

        # Creating  AttributeType's, RelationType's and SystemType's by json file as input
        if json_file:
          a = json_file.name.split('/')
          if a[-1] == 'ATs.json':
            json_data = json.loads(json_file.read())
            create_ats(json_data,user_id)

          elif a[-1] == 'RTs.json':
            json_data = json.loads(json_file.read())
            #print json_data,"Test_RTS json"
            create_rts(json_data,user_id)

          elif a[-1] == "STs.json":
            json_data = json.loads(json_file.read())
            #print json_data,"Test_STs json"
            create_sts(json_data,user_id)

          else:
            print 'file name should be ATs.json,STs.json or RTs.json to load Ats,STs or RTs of json'
        
        # Retrieve 'Quiz' GSystemType's id -- in order to append it to 'meta_type_set' for 'QuizItem' GSystemType
        quiz_type = node_collection.one({'_type': u'GSystemType', 'name': u'Quiz'})
        quiz_item_type = node_collection.one({'_type': u'GSystemType', 'name': u'QuizItem'})
        
        # Append quiz_type, options & correct_answer to attribute_type_set of 'QuizItem'
        if not quiz_item_type.attribute_type_set:
          quiz_item_type.attribute_type_set.append(node_collection.one({'_type': u'AttributeType', 'name': u'quiz_type'}))
          quiz_item_type.attribute_type_set.append(node_collection.one({'_type': u'AttributeType', 'name': u'options'}))
          quiz_item_type.attribute_type_set.append(node_collection.one({'_type': u'AttributeType', 'name': u'correct_answer'}))
          quiz_item_type.save()
        
        # Append start_time & end_time to attribute_type_set of 'Quiz'
        if not quiz_type.attribute_type_set:
          quiz_type.attribute_type_set.append(node_collection.one({'_type': u'AttributeType', 'name': u'start_time'}))
          quiz_type.attribute_type_set.append(node_collection.one({'_type': u'AttributeType', 'name': u'end_time'}))
          quiz_type.save()

        #Creation Gsystem Eventtype as a container to hold the Event types
        glist = node_collection.one({'_type': "GSystemType", 'name': "GList