#!/usr/bin/python

import sys
import getopt
import glob
import os
import readline

sys.path.insert(0,'/usr/share/soul/')

from ve_engine import Ve
from ve_db import VeDB, VeDBException

class Options(object):
	def __init__(self, argv):
		self.input = None
		self.debug = False
		try:
			opts, self.args = getopt.getopt(argv, "tv", ["theory", "vocabulary"])

		except getopt.GetoptError:
			self.usage()
		for opt, arg in opts:
			if opt in ("-t", "--theory"):
				self.theory()
			if opt in ("-v", "--vocabulary"):
				self.vocabulary()
			elif opt in ("-h", "--help"):
				self.usage()

#		cmds=('create', 'twin', 'edit', 'scan', 'expand', 'parentize', 'aura') 

		if len(self.args)<1:
			self.usage()
		self.command = self.args[0]

     		

		if self.command == 'create':
			if len(self.args)!=2:
				self.usage()
			self.input = self.args[1]

		if self.command == 'twin':
			if len(self.args)!=3:
				self.usage()
			self.alias = self.args[1]
			self.orig = self.args[2]

		if self.command == 'edit':
			if len(self.args)!=2:
				self.usage()
			self.input = self.args[1]


               	if self.command == 'scan':
                       	if len(self.args)==1:
                               	self.input = None
                       	elif len(self.args)==2:
				self.input = self.args[1]

		if self.command == 'expand':
			if len(self.args)<2 or len(self.args)>3:
				self.usage()
			self.input = self.args[1]

			if len(self.args)==3:
				self.input2 = self.args[2]
			else:
				self.input2 = None

		if self.command == 'parentize':
			if len(self.args)!=3:
				self.usage()
			self.input = self.args[1]
			self.input2 = self.args[2]


                if self.command == 'aura':
			if len(self.args)<2 or len(self.args)>3:
				self.usage()
			self.input = self.args[1]		

		if (not self.command in ('create', 'scan', 'twin', 'edit', 'expand', 'parentize', 'aura')): 

         		self.error()



        def usage(self):
		print """
    Welcome to Virtual Entity!

    Usage: soul [options] <command> ...

    Commands:
    create <FILE>               Create soul of <FILE>
    scan [<FILE>]               Scan  directory or visualize soul of <FILE> 
    twin <FILE1> <FILE2>        Twins <FILE2> to Soul of <FILE1> [ex foo.mov, foo.ogg]
    edit <FILE>                 Add metadata or edit soul metadata of <FILE>        
    expand <FILE>               Expand soul of <FILE> with aura annotation      
    parentize <FILE1> <FILE2>   Genetic relation, <FILE1> is ancestor of <FILE2>
    aura <FILE>			Insert relations and annotations

    Options:
    -h, --help                  Show usage
    -t, --theory		Show theory
    -v, --vocabulary		Show vocabulary
    ------------------------------------------------------------------------------------------>

    Use this utility to set metadata and license of your digital files.

    http://virtualentity.org/ 

		"""
                sys.exit(2)


        def error(self):
                print """
    Command not found. Please type:
    soul --help to read the help file!
                """
                sys.exit(2)


        def vocabulary(self):
		print """
     Virtual Entity's terminology:
     
     soul = metadata set of a file
     aura = space around the soul where file's relations and user's annotations are stored
     substance = if a file is an 'audio', 'video', 'text' or 'image' file
     twin = two files are twins when they have the same content in a different format or 
            compression 
     parent = a file which was used in another file (also called 'ancestor')
     child = a file which uses another file is a 'child' (or a descendent) of it
     natural born digital = a file which was created inside a computer using material created 
                            inside a computer
     natural born analogue = a file which was made using material that has an analogue relation 
                             with the real world, and a carrier
     native file = the first copy (or original, it's the same) of a file which reaches the Net 
     ----------------------------------------------------------------------------------------->
      		"""
		sys.exit(2)

	def theory(self):
		print """


                           ...              
            'c:.          ,k0l.             
            .:0N0d;.     .cKWO,              
              'l0NNKd'  'dXNk;               
                .:xXN0ddONWK;                
                  ,xNMMMMMWXdccccl:'         
            .;clldOXWMMMMMMMWWWWWWNx.        
           .oNMMMWNKkxONWW0dox0NMMWk.        
            :0WMW0l. .'kN0c   'OMMW0;....    
            .oXMWk,   .oXXl   'kWMMWXKKXOc.  
        .. .'dXMMNk,..:OWNkclkKNWWWWWMMMNk.  
       ,kKKKXNNXXXKK00KKKK0Okxdollcco0WMWk.  
      .cXMMMNO:'...''''.....        .dWMWk.  
       ,0WMMWO.                  ..;dKWN0l.  
       .lKWMMXc.               ,dKK0Oxo:.    
        .ck0KKOxl,.            .,;,.         
            .....                            
                                        
    	

    Virtual Entity is a research project (and a work of art) starting from 
    the assumption that the concepts of authenticity, ownership, uniqueness 
    and seriality are, within the digital domain, no longer valid. In fact 
    there is no substantial difference between copy and original on the Web, 
    and these two categories are not relevant. Since any file can generate an 
    infinite number of entities identical to itself, there is no scarcity on 
    the Net, and any resource is indefinitely available. Assuming possession 
    is related to the numerical proportion between resources (objects) and 
    potential owners (subjects), then, whereas resources are not limited, 
    the concept of ownership and the idea of property become superfluous.

    The practical method to achieve such result is this simple application 
    specifically developed to release, license, and catalogue digital files. 
    This system, transforming the traditional approach towards metadata, 
    which are here stored on a database online (and not in the file's header), 
    is based on the idea that any file is an independent creation living its 
    own life and experiencing various levels of transformation and progressive 
    generation (of meaning, shape, and entities) in the course of its virtual 
    existence. This way digital resources, interpreted as cultural units, are 
    considered the main actors of the web.

    If this didn't confuse you enough, 
    please visit http://virtualentity.org/ 
		"""
		sys.exit(2)


def raw_input_field(meta, key):
        if (not meta) or (not meta.has_key(key)):
                return raw_input(' : ')
        result = raw_input('['+str(meta[key])+'] : ')
        if result == "":
                return meta[key]
        return result




# Function that prints soul status for infile
def print_status(soul, verbose, parent_verbose):
        if soul.has_key('alias_id'):
                print "        -> Soul detected" 
        else:
                print "        -> Soul detected" 
# todo: add secret command to display soul id and check better the aliasing


        if soul['substance']:
                meta = ve.get_meta_from_soul(soul)
                if soul['substance']=='T':
                        print "        -> Text metadata"
                if soul['substance']=='A':
                        print "        -> Audio metadata"
                if soul['substance']=='V':
                        print "        -> Video metadata"
                if soul['substance']=='I':
                        print "        -> Image metadata"
		if verbose:
			print "\n"
#		print "        ................................."
                print "        Title: " + meta['title']
                print "        Author: " + meta['author']
                if verbose:
                        print "        Year of creation: " + meta['year_of_creation']
                        print "        Date of upload: " + meta['date_of_upload']
                        print "        Place of creation: " + meta['place_of_creation']
                        print "        Subject: " + meta['subject']
			if soul['substance'] != 'I':
                        	print "        Language: " + meta['language']
                        print "        Publisher: " + meta['publisher']
                        print "        Collection: " + meta['collection']
                        if soul['substance'] == 'T':
                                print "        Pages: " + meta['pages']
                                print "        First edition year: " + meta['first_edition_year']
                                print "        ISBN: " + meta['isbn']
                        if soul['substance'] == 'V':
                                print "        Duration: " + meta['duration']
                        if soul['substance'] == 'I':
                                print "        Size: " + meta['size']
                        print "        Keywords: " + meta['keywords']
                        print "        Type/Genre: " + meta['type']
                        print "        Natural born: " + meta['natural_born']
                        if meta['natural_born'] == 'D':
                                print "        Creation software: " + meta['creation_software']
                        else:
                                print "        Carrier: " + meta['carrier']
                                print "        Digitisation process: " + meta['digitisation_process']
                        if soul['substance'] == 'V':
                                print "        System: " + meta['system']
                                print "        Short content: " + meta['short_content']
                                print "        Sound: " + meta['sound']
                                print "        Color/BW: " + meta['color']
                                print "        Titles: " + meta['announcing_titles']
                                print "        Credits: " + meta['credits']
                        print "        Related URL: " + meta['url']
                        print "        Suggestions: " + meta['fruition_suggestions']
                        print "        Future plans: " + meta['future_plans']
                        print "        Virtual Entity Status: " + meta['ve_status']
                        if meta['ve_status'] == 'N':
	                        print "        License: " + meta['license']
			if meta['ve_status'] == 'Y':
			        print "        License: Virtual Entity"
			print "\n"
#		else: 
#			print "\n"
#			print "        ................................."
		

        if verbose:
		print "          -> Aura detected"
#                print "        ................................."
                annotations = ve.get_annotations_from_soul(soul)
                for ann in annotations:
                        print "        Note inserted " + ann['date'] + ": " + ann['text']

        cousins = ve.get_cousins_from_soul(soul)
        if len(cousins)>0:
                for cousin in cousins:
                        if parent_verbose:
#                                print "------------------------------------------------"
#                                print "        -> Have the following semantic relation:"
#                                print "------------------------------------------------"
#                                print_status(cousin, True, False)
#                                print "----------------------------------------------"
#                        else:
                                parent_meta = ve.get_meta_from_soul(cousin)
                                print "        -> Semantic relation:"
                                print "            Title: " + parent_meta['title']
                                print "            Author: " + parent_meta['author']

        parents = ve.get_parents_from_soul(soul)
        if len(parents)>0:
                for parent in parents:
                        if parent_verbose:
#                                print "------------------------------------------------"
#                                print "        -> Have the following ancestor:"
#                                print "------------------------------------------------"
#                                print_status(parent, True, False)
#                                print "----------------------------------------------"
#                        else:
                                parent_meta = ve.get_meta_from_soul(parent)
                                print "        -> Ancestor:"
                                print "            Title: " + parent_meta['title']
                                print "            Author: " + parent_meta['author']
        children = ve.get_children_from_soul(soul)
        if len(children)>0:
                for child in children:
                        if parent_verbose:
#                                print "------------------------------------------------"
#                                print "        -> Have the following descendent:"
#                                print "------------------------------------------------"
#                                print_status(child, True, False)
#                                print "----------------------------------------------"
#                        else:
                                child_meta = ve.get_meta_from_soul(child)
                                print "        -> Descendent:"
                                print "            Title: " + child_meta['title']
                                print "            Author: " + child_meta['author']
	print "\n"


# Main program (in girum imus nocte et consumimur igni)

if __name__ == "__main__":
	opts = Options(sys.argv[1:])
	ve = Ve()
	ve.connect("db.virtualentity.org")




	# Get Soul information interactively from console...
	if opts.command == 'create':
		print "Initialising Soul for " + opts.input + "."

	if opts.command == 'edit' or opts.command == 'create':
		edited_soul = ve.get_soul(opts.input)
		if edited_soul:
			if not ve.check_ownership(edited_soul, ""):
				print "Soul exists. Please insert password:",
				opts.password = raw_input()
				if not ve.check_ownership(edited_soul, opts.password):
					print "Wrong password. Access denied."
					sys.exit(0)
			else:
				print "This Soul is open!"
				print "Please enter new password (or press ENTER to leave Soul open):",
				opts.password = raw_input()
				ve.change_soul_password(edited_soul, opts.password)
				
			meta = ve.get_meta_from_soul(edited_soul)
		else:
			meta = { }

		natural_born = ""
		color = ""
		ve_status = ""

		if not edited_soul:
			substance = ""
			while (not substance in ('text', 'audio', 'video', 'image')):
				print "Substance [text, audio, video, image]:",
				substance = raw_input()
			print "Define " + substance + " Soul."
		else:
			substance = edited_soul['substance']
			if substance=='T': substance='text'
			if substance=='A': substance='audio'
			if substance=='V': substance='video'
			if substance=='I': substance='image'
			print "Define " + substance + " soul."

		print "Title",
		meta['title'] = raw_input_field(meta, 'title')
		print "Author",
		meta['author'] = raw_input_field(meta, 'author')
		print "Year (of creation)",
		meta['year_of_creation'] = raw_input_field(meta, 'year_of_creation')
		print "Date (of upload) (format: YYYY-DD-MM)",
		meta['date_of_upload'] = raw_input_field(meta, 'date_of_upload')
		print "Place (of creation)",
		meta['place_of_creation'] = raw_input_field(meta, 'place_of_creation')
		print "Subject",
		meta['subject'] = raw_input_field(meta, 'subject')
		if substance != 'image':
			print "Language (main)",
			meta['language'] = raw_input_field(meta, 'language')
		print "Publisher",
		meta['publisher'] = raw_input_field(meta, 'publisher')
		print "Collection",
		meta['collection'] = raw_input_field(meta, 'collection')

		if substance == 'text':
			print "Pages",
			meta['pages'] = raw_input_field(meta, 'pages')
			print "First edition year",
			meta['first_edition_year'] = raw_input_field(meta, 'first_edition_year')
			print "ISBN",
			meta['isbn'] = raw_input_field(meta, 'isbn')
		if substance == 'audio':
			print "Duration",
			meta['duration'] = raw_input_field(meta, 'duration')
		if substance == 'video':
			print "Duration",
			meta['duration'] = raw_input_field(meta, 'duration')
		if substance == 'image':
			print "Size",
			meta['size'] = raw_input_field(meta, 'size')

		print "Keywords",
		meta['keywords'] = raw_input_field(meta, 'keywords')
		print "Type/Genre",
		meta['type'] = raw_input_field(meta, 'type')

		while natural_born not in ('D', 'A'):
			print "Natural Born ('D' for digital or 'A' for analogue)",
			natural_born = raw_input_field(meta, 'natural_born')
			meta['natural_born'] = natural_born
		if meta['natural_born'] == 'A':
			print "Carrier",
			meta['carrier'] = raw_input_field(meta, 'carrier')
			print "Digitisation Process",
			meta['digitisation_process'] = raw_input_field(meta, 'digitisation_process')
			meta['creation_software'] = ""
		else:
			print "Creation software",
			meta['creation_software'] = raw_input_field(meta, 'creation_software')
			meta['carrier'] = ""
			meta['digitisation_process'] = ""

		if substance == 'audio':
			print "Short content",
			meta['short_content'] = raw_input_field(meta, 'short_content')
			print "Sound (stereo/mono)",
			meta['sound'] = raw_input_field(meta, 'sound')

		if substance == 'video':
			print "System (PAL, NTSC)",
			meta['system'] = raw_input_field(meta, 'system')
			print "Short content",
			meta['short_content'] = raw_input_field(meta, 'short_content')
			print "Sound",
			meta['sound'] = raw_input_field(meta, 'sound')
			while not color in ('C', 'BW'):
				print "Color ('C' for color or 'BW' for black/white)",
				color = raw_input_field(meta, 'color')
				meta['color'] = color
			print "Titles",
			meta['announcing_titles'] = raw_input_field(meta, 'announcing_titles')
			print "Credits",
			meta['credits'] = raw_input_field(meta, 'credits')

		print "Related URL",
		meta['url'] = raw_input_field(meta, 'url')
		print "Suggestions",
		meta['fruition_suggestions'] = raw_input_field(meta, 'fruition_suggestions')
		print "Future plans",
		meta['future_plans'] = raw_input_field(meta, 'future_plans')

		while ve_status not in ('Y', 'N'):
			print "Virtual Entity Status ('Y' if Virtual Entity, or 'N' if you wish to use another license)",
			ve_status = raw_input_field(meta, 've_status')
			meta['ve_status'] = ve_status
		if meta['ve_status'] == 'N':
			print "License",
			meta['license'] = raw_input_field(meta, 'license')
		else:
			meta['license'] = "Virtual Entity"
			print "This is a Virtual Entity."

	if opts.command == 'create' and not edited_soul:
		print "Please provide an access password for Soul (or press ENTER to leave Soul open):",
		opts.password = raw_input()

	# ...and create soul in database.
	if opts.command == 'create':
		try:
			if not edited_soul:
				ve.create(opts.input, opts.password)
				print "Soul created."
		except IOError, (errno, strerror):
			print "Error: %s" % (strerror)
		except VeDBException, (errno, strerror):
			print "Error: %s" % (strerror)

	if opts.command == 'edit' or opts.command == 'create':
		if edited_soul:
			ve.remove_meta(edited_soul, opts.password)
		if substance == 'text':
			ve.add_text_meta(opts.input, opts.password, meta)
		if substance == 'audio':
			ve.add_audio_meta(opts.input, opts.password, meta)
		if substance == 'video':
			ve.add_video_meta(opts.input, opts.password, meta)
		if substance == 'image':
			ve.add_image_meta(opts.input, opts.password, meta)
		if edited_soul:
			print "Soul updated."
                
#		 	print "May the Entity be with you!"				

# ...whenever a body is by nature divisible through and through, whether by bisection or...

	if opts.command == 'aura':
		print "You are now writing in the Aura of the Soul of " + opts.input

		resp = ""
		resp1 = ""
		print "Do you want to add a descendent to this file (Y/N)?",
		resp1 = raw_input()
		if resp1=='Y':
			print "Insert child filename:",
			child = raw_input()
				
			print "Making " + child + " descendent of " + opts.input
			ve.parentize(opts.input, child)	

			print "Do you want to add another descendent to this file (Y/N)?",
			resp = raw_input()
			if resp=='Y':
				print "Insert child filename:",
				child = raw_input()

				print "Making " + child + " descendent of " + opts.input
				ve.parentize(opts.input, child)
				resp = ""
			

		resp = ""
		resp2 = ""
		print "Do you want to add ancestors to this file (Y/N)?",
		resp2 = raw_input()
		if resp2=='Y':
			print "Insert ancestor filename:",
			parent = raw_input()

			print "Making " + parent + " ancestor of " + opts.input
			ve.parentize(parent, opts.input)

			print "Do you want to add another ancestors to this file (Y/N)?",
			resp = raw_input()
			if resp=='Y':
				print "Insert ancestor filename:",
				parent = raw_input()

				print "Making " + parent + " ancestor of " + opts.input
				ve.parentize(parent, opts.input)
				resp = ""

		resp = ""
		resp3 = "" 

		print "Do you want to add a semantic relation to this file (Y/N)?",
		resp3 = raw_input()
		if resp3=='Y':
			print "Insert related filename:",
			related = raw_input()

			print "Making " + related + " semantically connected to " + opts.input
			ve.add_annotation('', opts.input, related)
			
			print "Do you want to add another semantic relation to this file (Y/N)?",
			resp = raw_input()
			if resp=='Y':
				print "Insert related filename:",
				related = raw_input()

				print "Making " + related + " semantically connected to " + opts.input
				ve.add_annotation('', opts.input, related)
				resp= ""
				
		resp = ""
		resp4 = ""

		print "Do you want to expand soul of " + opts.input + " with annotation (Y/N)?",
		resp4 =raw_input() 
		if resp4=='Y':		
			print "Insert text:",
                 	text = raw_input()
                 	ve.add_annotation(text, opts.input, '')

			print "Do you want to expand soul of " + opts.input + " with another annotation (Y/N)?",	
			resp = raw_input()
			if resp=='Y':
				print "Insert text:",
				text = raw_input()
				ve.add_annotation(text, opts.input, '')

		if resp1==resp2==resp3==resp4=='N':
			print "Better a small aura than one full of garbage." 
		
		else:
			print "Aura expanded!"

			print "May the Entity be with you!"
         


	if opts.command == 'twin':
		soul = ve.add_alias(opts.orig, opts.alias)


        if opts.command == 'scan':
		print "\nScanning ",
		if opts.input:
			print "\n",
			soul = ve.get_soul(opts.input)
			if not soul:
				print opts.input + " soul not found"
			else:
				print opts.input + ":"
				print_status(soul, True, True)
		else:
			print "directory for souls:\n"
			for infile in glob.glob('*'):
				if os.path.isfile(infile):
					soul = ve.get_soul(infile)
					if not soul:
						print infile + " soul not found"
					else:
						print infile + ":"
						print_status(soul, False, False)


	if opts.command == 'parentize':
		print "Making " + opts.input + " ancestor of " + opts.input2
		ve.parentize(opts.input, opts.input2)
	
	if opts.command == 'expand':
		print "Adding annotation to expand soul of " + opts.input,
		if opts.input2:
			print " and " + opts.input2
		else:
			print
		print "Insert text:",
		text = raw_input()
		ve.add_annotation(text, opts.input, opts.input2)


# Digital artificial world is structured by specific rules that are somewhat different from those expressed 
# and manifested in the physical world we normally experience. One relevant difference is the definition of identity  
# If software, as source code, is considered text, an executable is something more malicious, composed, an organon 
# activating a different functioning. Be software a daemon, or a polumetis spirit, it is not a simple entity.

# vi:ts=4











