
#require 'rubygems'
require 'toodledo'

class ToodleDoSyncer < OSX::NSObject

 def session
	return @session if @session
	unless @session 
		apiKey=ToodleDoPreferences.apiKey
		password=ToodleDoPreferences.password
		if (! apiKey || apiKey.length < 0 || ! password || password.length < 0) then
			doErrorAlert
			return
		end
		begin
			@session = Toodledo::Session.new(ToodleDoPreferences.apiKey,ToodleDoPreferences.password)
			@session.connect()
		rescue
			@session=nil
			return nil
		end
	end
	@session
 end
 
 def doErrorAlert
			alrt=NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat("Error syncing ToodleDo. Check your API key and password!","OK",nil,nil,"")
			alrt.runModal
 end

 def clean(moc)
	return unless session
	session.get_tasks().each{ |t| session.delete_task(t.server_id); print "deleted task #{t.server_id}\n" }
	session.get_contexts().each {|c| session.delete_context(c.server_id); print "deleted context #{c.server_id}\n"}
	session.get_folders().each { |f| session.delete_folder(f.server_id); print "deleted folder #{f.server_id}\n"}
	moc.objectsForEntityNamed('Action').each { |a| a.toodleID=nil}
	moc.objectsForEntityNamed('Context').each { |c| c.toodleID=nil}

 end
 
 def makeToodleFolder(f)
	f.toodleID=session.add_folder(f.name(),false)
	print "added folder #{f.name()} #{f.toodleID}\n"
 end
 
  def makeToodleTask(t)
    return if t.toodleID? 
	if t.parent?
		makeToodleTask(t.parent)
	end
	if t.isArea?
		makeToodleFolder(t)
		return
	end
	args ={}
	if (t.context?)
		makeToodleContext(t.context)
		args[:context]=t.context().toodleID() if t.context.toodleID?
	end
	args[:tag] = "F-"
	if (t.parent?)
		if (t.parent.isArea?)
			args[:folder]=t.parent.toodleID
		else
			args[:parent] = t.rootProject().toodleID if t.rootProject() != nil
			args[:folder] = t.rootArea().toodleID if t.rootArea() != nil
		end
		if (t.parent != t.rootProject() && t.parent != t.rootArea())
			args[:tag] = "F- "+ t.parent.name
		end
	end
	if (t.isImportant? && t.isUrgent? && t.isNext?)
		args[:priority]=3 
	elsif (t.isImportant? && t.isUrgent?)
		args[:priority]=2
	elsif (t.isImportant?)
		args[:priority]=1
	elsif (t.isUrgent?)
		args[:priority]=0
	end
	print "making task #{t.name()}, #{args}\n"
	begin
		t.toodleID=session.add_task(t.name(),args)
		print "added task #{t.name()} #{t.toodleID}\n"
		if t.done? || t.note? then
			args={}
			args[:completed]=t.done?
			args[:note]=t.noteString
			session.edit_task(t.toodleID,args)
		end
		return t.toodleID
	rescue
		print "error making a task on toodle\n"
	end
	return nil
  end
  
  def makeToodleContext(c)
	if (!c.toodleID?)
		print "adding context #{c.name}\n"
		c.toodleID=session.add_context(c.name)  
		print "added context #{c.name} #{c.toodleID}\n"
	end
  end

 def findObjectByName(moc,entity,value)
    ed=NSEntityDescription.entityForName_inManagedObjectContext(entity,moc)
    request=NSFetchRequest.alloc.init
    request.setEntity(ed)
    pred=NSPredicate.predicateWithFormat_argumentArray("name BEGINSWITH[c] %@",[value])
    request.setPredicate(pred)
    sort=NSSortDescriptor.alloc.initWithKey_ascending("name",true)
    request.setSortDescriptors([sort])
    error=0
    result=moc.executeFetchRequest_error(request,nil)
    return result[0] if result && result.count > 0
    return nil
  end
  
  def pushCompleted(task)
	begin
	    print "pushing done for #{task.title}\n"
		session.edit_task(task.server_id,{:completed=>'true'})
	rescue
	end
  end

  def syncAll(moc)
    print "toodling\n"
	
	toodleC=session.get_contexts()
  	toodleC.each do | c |
  		ourC = findObjectByName(moc,"Context",c.name())
		ourC.toodleID = c.server_id if ourC && !ourC.toodleID
		if (!ourC && c.name() != "--Context--")
			print "adding new Context #{c.name} from Toodle\n"
			newC = NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Context",moc)
			newC.toodleID = c.server_id
			newC.name=c.name()
		end
  	end

	ourTasks=moc.objectsForEntityNamed('Action')
	return unless session # try to connect

	@toodleIDLookup={}
	ourTasks.each do |t|
		unless t.toodleID?
		   print "Making #{t.name} on Toodledo\n"
		   makeToodleTask(t) if t.name
		end
		@toodleIDLookup["#{t.toodleID}"]=t
	end
	#print @toodleIDLookup
	
	toodleT=session.get_tasks()
	toodleT.each do |t| 
		if (t.tag && t.tag.match('F-')) # we put it there, we own it
			ourT=@toodleIDLookup[t.server_id]
			ourT=@toodleIDLookup["#{t.server_id}"] if !ourT
			if ourT then
				print "found our task on toodle\n"
				ourT.setDone(1) if t.completed? && !ourT.done?
				pushCompleted(t) if !t.completed? && ourT.done?
			else
				# we no longer have it, must be deleted
				print "deleting task #{t.title}/#{t.server_id} on Toodle\n"
				session.delete_task(t.server_id)
			end
		else
			# New to Toodle Do. Make it ours
			print "found a new todo on toodle. Importing #{t.title}\n"
			string = t.title
			ourTP=nil
			if (t.parent_id && @toodleIDLookup[t.parent_id])
				ourTP = @toodleIDLookup[t.parent_id]
			end
			
			if t.context 
				string << " @#{t.context.name}"
			end
			newA = NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Action",moc)
			newA.toodleID = t.server_id
			newA.smartName=string
			newA.setDone(1) if t.completed?
			newA.setParent(ourTP) if ourTP
			@toodleIDLookup["#{newA.toodleID}"]=newA
			s = t.tag
			if s
				s << " F-"
			else
				s="F-"
			end
			session.edit_task(t.server_id,{:tag => s})
		end
	end

		
  end

end