<?php

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

	private $_currentUser;
	private $_tablePrefix;
	
    /**
     * map timezone offsets to a name as used by Atmail. Just maps 
     * to a timezone for that offset, may not necessarily be
     * the correct actual location for the user.
     */
    private $_tzOffsets = array(
        '-11'   => "Pacific/Pago_Pago",
        '-10'   => "Pacific/Honolulu",
        '-9.5'  => "Pacific/Marquesas",
        '-9'    => "America/Anchorage",
        '-8'    => "America/Los_Angeles",
        '-7'    => "America/Denver",
        '-6'    => "America/Chicago",
        '-5'    => "America/New_York",
        '-4.5'  => "America/Caracas",
        '-4'    => "America/Halifax",
        '-3.5'  => "America/St_Johns",
        '-3'    => "America/Sao_Paulo",
        '-2'    => "America/Noronha",
        '-1'    => "Atlantic/Azores",
        '0'     => "Europe/London",
        '1'     => "Europe/Berlin",
        '2'     => "Europe/Athens",
        '3'     => "Asia/Bahrain",
        '3.5'   => "Asia/Tehran",
        '4'     => "Europe/Moscow",
        '4.5'   => "Asia/Kabul",
        '5'     => "Asia/Karachi",
        '5.5'   => "Asia/Colombo",
        '5.75'  => "Asia/Kathmandu",
        '6'     => "Asia/Dhaka",
        '6.5'   => "Indian/Cocos",
        '7'     => "Asia/Bangkok",
        '8'     => "Australia/Perth",
        '8.75'  => "Australia/Eucla",
        '9'     => "Asia/Tokyo",
        '9.5'   => "Australia/Adelaide",
        '10'    => "Australia/Sydney",
        '10.5'  => "Australia/Lorde_Howe",
        '11'    => "Asia/Vladivostok",
        '11.5'  => "Pacific/Norfolk",
        '12'    => "Pacific/Auckland",
        '12.75' => "Pacific/Chatham",
        '13'    => "Pacific/Tongatapu",
    );
        
	public function __construct($rcDbConfPath, $account=null)
	{
        require_once($rcDbConfPath);
        
        if (!preg_match("|^mysql://|", $rcmail_config['db_dsnw'])) {
            die("Only migrations from Roundcube using MySQL is supported\n");
        }
        
        $rcmail_config['db_dsnw'] = preg_replace("|^mysql://|", "", $rcmail_config['db_dsnw']);
        $pos = strrpos($rcmail_config['db_dsnw'], "/");
        $name = substr($rcmail_config['db_dsnw'], $pos + 1);
        $rest = substr($rcmail_config['db_dsnw'], 0, $pos);
        
        $pos = strrpos($rest, "@");
        $host = substr($rest, $pos + 1);
        $userAndPass = substr($rest, 0, $pos);
        
        $pos = strpos($userAndPass, ":");
        $dbuser = substr($userAndPass, 0, $pos);
        $dbpass = substr($userAndPass, $pos + 1);
        
        $this->_db = Zend_Db::Factory("Pdo_Mysql", array(
            "host"           => $host,
            "username"       => $dbuser,
            "password"       => $dbpass,
            "dbname"         => $name,
        ));
        
        $this->_tables['users'] = $rcmail_config['db_table_users'];
        $this->_tables['contacts'] = $rcmail_config['db_table_contacts'];
        $this->_tables['identities'] = $rcmail_config['db_table_identities'];
        
        if ($this->_rcSupportsGroups($rcmail_config)) {
            $this->_tables['contactgroups'] = $rcmail_config['db_table_contactgroups'];
            $this->_tables['contactgroupmembers'] = $rcmail_config['db_table_contactgroupmembers'];
        }
        
        if (empty($account)) {
            // query for list of Roundcube users
            $this->_rcUsers = $this->_db->fetchAll(
                "select user_id, username, language, preferences 
                from {$this->_tables['users']}"
            );
        } else {
            $this->_currentUser = new Atmail_Migrate_Data_User();
            $this->_currentUser->name($account);
            $this->_migrateSingleUser = true;
        }
            
	}
	
	public function fetchUser()
	{
	    if ($this->_migrateSingleUser) {
	        return $this->_currentUser;
        }
        
        if (!isset($this->_rcUsers) || empty($this->_rcUsers)) {
            return false;
        }
        
        $row = array_pop($this->_rcUsers);
        
        // reset list of user's contacts and groups
        unset($this->_contacts);
        unset($this->_contactGroups);
        
        $settings = $this->_db->fetchRow(
            "select `name`, `reply-to`, `signature` 
            from {$this->_tables['identities']} 
            where standard = 1 and user_id = ? and email = ?", 
            array($row['user_id'], $row['username'])
        );
        
		$user = new Atmail_Migrate_Data_User();
        $user->name($row['username']);
        $user->realName($settings['name']);
        $user->replyTo($settings['reply-to']);
        $user->signature($settings['signature']);
        $user->language($row['language']);
        $this->_currentUser = $user->name();
		return $user;
	}
	
	public function fetchEmail()
	{
        return false;
	}
	
	public function fetchContact()
	{
		if (!isset($this->_contacts)) {
            $userId = $this->_db->fetchOne("select user_id from {$this->_tables['users']} where username = ?", $this->_currentUser->name()); 
            $this->_contacts = $this->_db->fetchAll("select email, firstname, surname, name from {$this->_tables['contacts']} where user_id = ?", $userId);
        }
        
        if (empty($this->_contacts)) {
            return false;
        }
        
        $c = array_pop($this->_contacts);
        
        $contact = new Atmail_Migrate_Data_Contact;
        $contact->email($c['email']);
        if (!empty($c['name']) && empty($c['firstname'])) {
            $contact->firstName($c['name']);
        } else {
            $contact->firstName($c['firstname']);
            $contact->lastName($c['surname']);
        }
        
        return $contact;
	}
	
    public function fetchSettings()
    {
        $settings = new Atmail_Migrate_Data_Settings;
        $data = $this->_db->fetchRow("select {$this->_tables['users']}.user_id, language, preferences, signature, name, `reply-to`
            from {$this->_tables['users']}, {$this->_tables['identities']} 
            where {$this->_tables['identities']}.user_id = {$this->_tables['users']}.user_id and 
            {$this->_tables['users']}.username = ? and standard = 1", $this->_currentUser->name());
        
        $preferences = unserialize($data['preferences']);
        if (isset($preferences['show_images'])) {
            $showImages = ($preferences['show_images'] > 0)? 1 : 0;
            $settings->displayEmailImages($showImages);
        }
        
        if (isset($preferences['draft_autosave'])) {
            $draftAutoSave = ($preferences['draft_autosave'] > 0)? 1 : 0;
            $settings->saveDrafts($draftAutoSave);
        }
        
        if (isset($preferences['timezone'])) {
            $settings->timeZone($this->_getTimeZone($preferences['timezone']));
        }
        
        $settings->realName($data['name']);
        $settings->language($data['language']);
        $settings->signature($data['signature']);
        $settings->replyTo($data['reply-to']);
        
        return $settings;
    }
    
    
    public function fetchContactGroup()
	{
        // If we're migrating from an old RC that does not support
        // contact groups then return false
        if (!isset($this->_tables['contactgroups'])) {
            return false;
        }
        
		if (!isset($this->_contactGroups)) {
            $userId = $this->_db->fetchOne(
                "select user_id 
                from {$this->_tables['users']} 
                where username = ?", $this->_currentUser->name()
            );
             
            $this->_contactGroups = $this->_db->fetchAll(
                "select name, contactgroup_id 
                from {$this->_tables['contactgroups']} 
                where user_id = ?", $userId
            );
        }
        
        if (empty($this->_contactGroups)) {
            return false;
        }
        
        $g = array_pop($this->_contactGroups);
        
        $members = $this->_db->fetchCol(
            "select email
            from {$this->_tables['contacts']}, {$this->_tables['contactgroupmembers']} 
            where {$this->_tables['contacts']}.contact_id = {$this->_tables['contactgroupmembers']}.contact_id 
            and contactgroup_id = ?", 
            $g["contactgroup_id"]
        );
        
        $group = new Atmail_Migrate_Data_ContactGroup;
        $group->name($g["name"]);
        $group->members($members);
        return $group;
	}
    
	public function fetchCalEvent()
	{
		return false;
	}
    
    private function _getTimeZone($offset)
    {
        if (isset($this->_tzOffsets[$offset])) {
            return $this->_tzOffsets[$offset];
        }
        
        return "";
    }

    private function _rcSupportsGroups($rcmail_config)
    {
        if (isset($rcmail_config['db_table_contactgroups'])) {
            try {
                $this->_db->fetchOne("select 1 from {$rcmail_config['db_table_contactgroups']} limit 1");
                return true;
            } catch (Exception $e) {
                return false;
            }
        } else {
            return false;
        }
    }
    
}
