<?php

/**
 * Migrate adapter for migrating from Zimbra to Atmail.
 *
 * @author Brad Kowalczyk <brad@staff.atmail.com>
 */
 
class Atmail_Migrate_Adapter_Zimbra implements Atmail_Migrate_Adapter_Interface {

	private $_currentUser;
	private $_zmAdmin;
    private $_host;
    private $_defaultPassword;
    private $_admin;
    private $_adminPass;
    
	public function __construct($admin, $password, $host, $dataFile, $defaultPassword)
	{
        $this->_host = $host;
        $this->_defaultPassword = (is_null($defaultPassword))? '' : $defaultPassword;
        $this->_admin = $admin;
        $this->_adminPass = $password;
        
	    if (empty($dataFile) || !is_readable($dataFile)) {
	        die("incorrect data file path or no read permissions\n");
	    }

        require_once("zimbraAdmin/zimbraAdmin.php");
        $this->_zmAdmin = new zimbraAdmin($host);
        if (!$res = $this->_zmAdmin->zimbra_login($admin, $password)) {
            die("login failed\n");
        }

	    $this->_fh = fopen($dataFile, 'r');
	}
	
	
	
	public function fetchUser()
	{	
        if (feof($this->_fh)) {
            return false;
        }
        
        $stop = false;
		$user = new Atmail_Migrate_Data_User();
        $pos = 0;
        
        while (false !== $line = fgets($this->_fh)) {
            $header = substr($line, 0, 4);
            
            if ($header == "Acc:" && $stop) {
                fseek($this->_fh, $pos);
                $this->_currentUsersGroups = array();
                $this->_currentUsersCalendars = array();           
                return $user;
            }
            
            $pos = ftell($this->_fh);
            
            if ($header == "Acc:") {   
                $username = trim(substr($line, 4));
                $user->name($username);
                $user->password($this->_defaultPassword);
                if ($this->_defaultPassword) {
					$this->_zmAdmin->zimbra_set_account_password($username, $this->_defaultPassword);
				}
                $settings = $this->_zmAdmin->zimbra_get_account($username, "name", 1);
                $this->_assignUserSettings($user, $settings['ACCOUNT']['A']);
                $this->_currentUser = $user;
		        $stop = true;
		    } elseif ($header == "Con:") {
		        $this->_currentUsersGroups[] = trim(substr($line, 4));
		    } elseif ($header == "Cal:") {
		        $this->_currentUsersCalendars[] = trim(substr($line, 4));
		    }
		}
		
		return $user;
	}
	
    private function _assignUserSettings($user, $settings)
    {
        $c = 0;
        if (!is_array($settings)) {
            fwrite(STDERR, "Could not save user settings\n");
            return;
        }

        foreach ($settings as $s) {
            
            if ($c == 5) {
                return;
            }
            
            switch ($s['N']) {
                case 'zimbraMailQuota' : $user->userQuota($s['DATA']);$c++;break;
                case 'displayName' :     $user->realName($s['DATA']);$c++;break;
                case 'zimbraPrefTimeZoneId' : $user->timeZone($s['DATA']);$c++;break;
                case 'zimbraPrefMailForwardingAddress' : $user->forward($s['DATA']);$c++;break;
                case 'zimbraPrefMailSignatureHTML' : $user->signature($s['DATA']);$c++;break;
            }
        }
    }

    public function fetchSettings()
    {
    }
    
	public function fetchEmail()
	{
	    $username = escapeshellarg($this->_currentUser->name());
	    $password = escapeshellarg($this->_defaultPassword);
	    
	    // Use imapsync to migrate the mail to the Atmail server
	    //echo `imapsync $username $password $this->_host`;
	    return false;
	}
	
	public function fetchContact()
	{
	    static $group;
	    static $header;
        
	    // If $this->_contacts is not set or at EOF then we need 
	    // to fetch the next group and it's contacts
		if (!isset($this->_contacts) || feof($this->_contacts)) {
				    
		    if (empty($this->_currentUsersGroups)) {
		        // no more contacts to migrate
		        return false;
		    }
		
		    $group = array_shift($this->_currentUsersGroups);
		    
		    $encGroup = rawurlencode($group);
		    $admin = $this->_admin;
		    $user = $this->_currentUser->name();
		    $pass = $this->_adminPass;
		    $filename = $user . "." . str_replace(" ", "", $group) . ".csv";
		    exec("curl --user $admin:$pass -k https://{$this->_host}:7071/home/$user/$encGroup > /tmp/$filename");
		    $this->_contacts = fopen("/tmp/$filename", "r");
            $header = fgetcsv($this->_contacts);
            if (!is_array($header) || empty($header) || is_null($header[0])) {
                return;
            }
        }

		// "company","department","dlist","email","email2","email3","fileAs","firstName","fullName",
		// "homeCity","homeCountry","homeFax","homePhone","homePostalCode","homeState","homeStreet",
		// "homeURL","jobTitle","lastName","middleName","mobilePhone","nickname","notes","type",
		// "workCity","workCountry","workFax","workPhone","workPhone2","workPostalCode","workState","workStreet","workURL"
		
        $data = fgetcsv($this->_contacts);
        if (!is_array($data) || is_null($data[0])) {
            return;
        }
        $c = array_combine($header, $data);
        $contact = new Atmail_Migrate_Data_Contact;
        $contact->UserEmail($c['email']);
        $contact->UserFirstName($c['firstName']);
        $contact->UserLastName($c['lastName']);
        $contact->UserMiddleName($c['middleName']);
        $contact->UserHomeMobile($c['mobilePhone']);
        $contact->UserHomePhone($c['homePhone']);
        $contact->UserHomeFax($c['homeFax']);
        $contact->UserWorkPhone($c['workPhone']);
        $contact->UserWorkFax($c['workFax']);
        $contact->UserWorkCompany($c['company']);
        $contact->UserWorkDept($c['department']);
        $contact->UserInfo($c['notes']);
        $contact->UserHomeAddress($c['homeStreet']);
        $contact->UserHomeCity($c['homeCity']);
        $contact->UserHomeState($c['homeState']);
        $contact->UserHomeCountry($c['homeCountry']);
        $contact->UserHomeZip($c['homePostalCode']);
        $contact->UserUrl($c['homeUrl']);
        $contact->UserWorkAddress($c['workStreet']);
        $contact->UserWorkCity($c['workCity']);
        $contact->UserWorkState($c['workState']);
        $contact->UserWorkZip($c['workPostalCode']);
        $contact->UserWorkCountry($c['workCountry']);
        $contact->GroupName($this->_groupNameCheck($group));
        
        return $contact;
	}
	
    public function fetchContactGroup()
	{
        static $index = 0;
        
        if (isset($this->_currentUsersGroups[$index])) {
            $group = new Atmail_Migrate_Data_ContactGroup;
            $name = $this->_currentUsersGroups[$index];
            $group->name($this->_groupNameCheck($name));
            $index++;
            return $group;
        }
        
        return false;
	}
    
	public function fetchCalEvent()
	{
		static $calendar;
        
	    // If $this->_calendars is not set or at EOF then we need 
	    // to fetch the next calendar and it's contacts
		if (!isset($this->_calendar) || feof($this->_calendar)) {
				    
		    if (empty($this->_currentUsersCalendars)) {
		        // no more calendars to migrate
		        return false;
		    }
		
		    $calendar = array_shift($this->_currentUsersCalendars);
		    
		    $encCal = rawurlencode($calendar);
		    $admin = $this->_admin>;
		    $user = $this->_currentUser->name();
		    $pass = $this->_adminPass;
		    $filename = $user . "." . str_replace(" ", "", $calendar) . ".csv";
		    exec("curl --user $admin:$pass -k https://{$this->_host}:7071/home/$user/$encCal > /tmp/$filename");
		    $this->_calendar = fopen("/tmp/$filename", "r");
		}
	
		if (!$ics = $this->_fetchEventIcs()) {
			return;
		}
		
		$event = new Atmail_Migrate_Data_CalendarEvent;
		$event->account = $user;
		$event->calendarName($calendar)
		$event->ics($ics);
		
		return $event;
	}
    
    
    private function _fetchEventIcs()
    {
		static $vCalendar = "";
		$event = "";
		$record = false;
		
		while (false !== $line = fgets($this->_calendar)) {
			
			if (trim($line) == "BEGIN:VCALENDAR") {
				$record = 1;
			}
			
			if (trim($line) == "END:VEVENT") {
				$event .= $line;
				return $vCalendar . $event . "END:VCALENDAR";
			}
				
			if (trim($line) == "BEGIN:VEVENT") {
				$record = 2;
			}
			
			if ($record == 1) {
				$vCalendar . = $line;
			} elseif ($record == 2) {
				$event .= $line;
			}
		}
		
		return false;
	}
		
			
    /**
     * Convert some standard Zimbra Address Book names
     * to equiv. Atmail group names
     * 
     * @param String $name
     * @return String
     */
    private function _groupNameCheck($name)
    {
        if ($name == "Emailed Contacts") {
            $name = "Remembered";
        } elseif ($name == "Contacts") {
            $name = "";
        }
        
        return $name;
    }
    
    private function _calNameCheck($name)
    {
        return $name;
    }

}
