<?php
/*
* Copyright (c) 2009-2010 ATMAIL. All rights reserved
* See http://atmail.com/license.php for license agreement
*
* Author: Atmail
*/

require_once('library/Atmail/Abook/AbookAbstract.php');
require_once('library/Atmail/Vcard.php');

class Atmail_Abook_CardDav extends Atmail_Abook_Abstract
{
	private $username		= '';
	private $password		= '';
	private $server			= 'localhost';
	private $port			= '8800';
	private $url			= '';
	private $url_protocol		= "http";
	private $constructed_url	= '';
	private $_dav_server;
	private $server_type		= 'at';
	
	public function __construct(array $args = null)
	{
			if( 	!isset($args['username']) 
			|| 	!isset($args['password'])
			|| 	!isset($args['server'])
			|| 	!isset($args['port'])
			|| 	!isset($args['url'])
			)
			{
				throw new Atmail_Exception('CardDav Contacts constructor requires full carddav fields in arguments array');
			}
			
			$this->username 	= $args['username'];
			$this->password		= $args['password'];
			$this->server 		= $args['server'];
			$this->port		= $args['port'];
			$this->url		= $args['url'];
			if(isset($args['url_protocol'])) 
				$this->url_protocol = $args['url_protocol'];
			$this->constructed_url	= $this->url_protocol . "://" . $this->server . ":" . $this->port . "/";
		require_once('Atmail/CalDav/caldav-client.php');
		$this->_dav_server = new CalDAVClient( $this->constructed_url , $this->username, $this->password, '');
		$this->_dav_server->SetUserAgent("Atmail");
		$this->server_type = $this->_dav_server->DoServerCheckType();
		$this->_vcard_processor = new Vcard();
		$this->allowedFields = array('UserEmail', 'UserEmail2', 'UserEmail3', 'UserEmail4', 'UserEmail5', 'UserFirstName', 'UserMiddleName', 'UserLastName', 'UserTitle', 'UserGender', 'UserDOB', 'UserHomeAddress', 'UserHomeCity', 'UserHomeState', 'UserHomeZip', 'UserHomeCountry', 'UserHomePhone', 'UserHomeMobile', 'UserHomeFax', 'UserURL', 'UserWorkCompany', 'UserWorkTitle', 'UserWorkDept', 'UserWorkOffice', 'UserWorkAddress', 'UserWorkCity', 'UserWorkState', 'UserWorkZip', 'UserWorkCountry', 'UserWorkPhone', 'UserWorkMobile', 'UserWorkFax', 'UserType', 'UserInfo', 'EntryID', 'UserInfo', 'DateModified', 'UserPhoto', 'Global', 'Shared');
	}
	
	public function TestServer()
	{
		
		$constructed_url	= $this->url_protocol . "://" . $this->server . ":" . $this->port . "/";
		
        require_once('library/Atmail/CalDav/caldav-client.php');
		
		try
		{
			$dav_server = new CalDAVClient( $constructed_url , $this->username, $this->password, '');
		}
		catch(Exception $e)
		{
			return FALSE;
		}
		$dav_server->SetUserAgent("Atmail");

		if($dav_server->DoServerCheckType($this->url) == APPLE_DAV_SERVER)
		{
			if($dav_server->GetCurrentPrincipal('') != false)
				return TRUE;
			else
				return FALSE;
		}
		return FALSE;

	}

	public function Count($groupID = '')
	{	
		return count($this->_dav_server->GetVcards(null, null, $this->url . '/'));	
	}
	
	public function populate_contact(array $contact)
	{
		foreach($this->allowedFields as $requiredField)
		{
			if(!isset($contact[$requiredField]))
			{
				$contact[$requiredField] = '';		
			}	
		}	
		return $contact;	
	}
	
	public function GetPhoto(array $arguments = null)
	{
		$contact = NULL;
		if(isset($arguments['id']))
		{
			// requesting a single contact
			$contact = $this->Get($arguments);	
		}
		$contacts[0] = $contact;
		
		return $contacts;
	}
	
	public function StorePhoto(array $arguments = null)
	{
		$contact = null;
		if(isset($arguments['id']))
		{
			// requesting a single contact
			$contact = $this->Get($arguments);	
		}
		
		if($contact == null)
			return FALSE;
		
		$contact['UserPhoto'] = $arguments['UserPhoto'];

		return $this->Modify($contact);
	}
	
	public function Get(array $arguments = null)
	{
		// TODO : ADD PARENT FILTERING!
		// ID USED DIRECTLY FOR HREF.
		if(isset($arguments['id']))
		{
			// requesting a single contact
			$contacts = $this->_dav_server->GetVcardByUid($arguments['id'], $this->url . '/');	
		}
		else
		{
			$contacts = $this->_dav_server->GetVcards(null, null, $this->url . '/');
		}

		foreach($contacts as &$contact)
		{
			$contact_temp = $this->_vcard_processor->viewPart($contact['data']);
			$contact_temp['id'] = $contact_temp['contactId'] = $contact_temp['UID'];
			$contact_temp['etag'] = $contact['etag'];
			$contact_temp['serverID'] = $arguments['serverID'];
			$contact_temp['href'] = $contact['href'];
			$contact_temp = $this->populate_contact($contact_temp);
			$contact = $contact_temp;
		}
		
		if(isset($arguments['id']))
		{
			$contacts = $contacts[0];
		}
		return $contacts;
	}
	
	public function Put(array $arguments = null)
	{
		$data = array();
		foreach($arguments['contact'] as $k => $v ) 
		{
			
			if($k == 'UserDOB' && empty($v))
				continue;
				
			if( in_array($k, $this->allowedFields ) )
				$data[$k] = $v;		
		}

		$data["UID"] = create_guid();
		$contact_vcard = $this->_vcard_processor->exportPart($data);
		$contact_vcard = $this->_vcard_processor->build('', $contact_vcard);
	
		$id = $this->_dav_server->DoPUTRequest($this->url . '/' . $data["UID"] . ".vcf" , $contact_vcard, '', "text/vcard; charset=utf-8");
		
		return $data["UID"];
	}

	public function Delete(array $arguments = null)
	{
		if(!isset($arguments['serverID']) || !isset($arguments['id']))
		{
			throw new Atmail_Exception('CardDav::Delete requires id and serverID fields.');
		}

		// requesting a single contact
		$contact = $this->_dav_server->GetVcardByUid($arguments['id'], $this->url . '/');	
		
		// store the contact
		$id = $this->_dav_server->DoDELETERequest($this->url . '/'. $contact[0]['href'], $contact[0]['etag']);
				
	}

	public function Modify(array $arguments = null)
	{
		parent::Modify($arguments);
		
		if(!isset($arguments['serverID']) || !isset($arguments['id']))
		{
			throw new Atmail_Exception('CardDav::Modify requires id and serverID fields.');
		}

		// requesting a single contact
		$contact = $this->_dav_server->GetVcardByUid($arguments['id'], $this->url . '/');	

		// perform the required modifications
		$contact_vcard = $this->_vcard_processor->exportPart($arguments, $contact[0]['data']);
		$contact_vcard = $this->_vcard_processor->build('', $contact_vcard);

		// store the contact
		$id = $this->_dav_server->DoPUTRequest($this->url . '/'. $contact[0]['href'], $contact_vcard, $contact[0]['etag'], "text/vcard; charset=utf-8");

		return $id;
	}

	public function Search(array $arguments = null)
	{		
		if(!isset($arguments['serverID']))
		{
			throw new Atmail_Exception('CardDav::Search requires serverID fields.');
		}
		
		if(isset($arguments['fuzzy']) && $arguments['fuzzy'] == 1)
		{
			$fuzzysearch = $arguments['UserEmail'];
			$filters = array(
					array("search" => 'contains', 'property' => 'FN', 'test' => $fuzzysearch),
					array("search" => 'contains', 'property' => 'NICKNAME', 'test' => $fuzzysearch),
					array("search" => 'contains', 'property' => 'N', 'test' => $fuzzysearch),				
					array("search" => 'contains', 'property' => 'EMAIL', 'test' => $fuzzysearch),
					array("search" => 'contains', 'property' => 'ADR', 'test' => $fuzzysearch),
					array("search" => 'contains', 'property' => 'TEL', 'test' => $fuzzysearch),
					array("search" => 'contains', 'property' => 'ORG', 'test' => $fuzzysearch)
					);
			$contacts = $this->_dav_server->SearchEntry($filters, $this->url . '/');	
			foreach($contacts as &$contact)
			{
				$contact_temp = $this->_vcard_processor->viewPart($contact['data']);
				$contact_temp['id'] = $contact_temp['contactId'] = $contact_temp['UID'];
				$contact_temp['etag'] = $contact['etag'];
				$contact_temp['serverID'] = $arguments['serverID'];
				$contact_temp['href'] = $contact['href'];
				$contact_temp = $this->populate_contact($contact_temp);
				$contact = $contact_temp;
			}
			return $contacts;
		}
		else
		{
			$contacts = $this->_dav_server->SearchEntry(array(array("search" => 'equals', "property" => 'FN', "test" => $arguments['fullname'])), $this->url . '/');	
			foreach($contacts as &$contact)
			{
				$contact_temp = $this->_vcard_processor->viewPart($contact['data']);
				$contact_temp['id'] = $contact_temp['contactId'] = $contact_temp['UID'];
				$contact_temp['etag'] = $contact['etag'];
				$contact_temp['serverID'] = $arguments['serverID'];
				$contact_temp['href'] = $contact['href'];
				$contact_temp = $this->populate_contact($contact_temp);
				$contact = $contact_temp;
			}
			if( empty($contacts[0]['id']) )
			{
				return 0;
			}
			else
			{
				return $contacts[0]['id'];
			}
		}
	}
}
	
