<?php
/**
 * Class represents records from table newsletter_user_subscription
 * {autogenerated}
 * @property int $subscription_id 
 * @property int $user_id 
 * @property int $list_id 
 * @property string $type enum('auto','user','unsubscribed')
 * @property int $is_active 
 * @see Am_Table
 */
class NewsletterUserSubscription extends Am_Record
{
    /** user subscribed automatically to this subscription */
    const TYPE_AUTO = 'auto';
    /** user specially agreed to receive this list */
    const TYPE_USER = 'user';
    /** user specially decied to unsubscribe from this list */
    const TYPE_UNSUBSCRIBED = 'unsubscribed';
    
    protected $_user;
    
    function enable($type = null, $throwExceptions=false)
    {
        if ($type !== null)
            $this->updateQuick('type', $type);
        try {
            if (!$this->is_active)
                if (!$this->getList()->getPlugin()->changeSubscription($this->getUser(), 
                                array($this->getList()->plugin_list_id), array(),
                        (!empty($this->begin_date) ? 
                        array($this->getList()->plugin_list_id => array('begin_date' => $this->begin_date, 'expire_date' => $this->expire_date)) : array())))
                    return $this; // do not update if call failed (!)
        } catch (Exception $e) {
            $this->getDi()->errorLogTable->log("EXCEPTION during subscribe user $this->user_id to list $this->list_id");
            $this->getDi()->errorLogTable->log($e);
            
            if($throwExceptions)
                throw $e;
            
            return $this;
        }
        $this->updateQuick('is_active', 1);
        return $this;
    }
    function disable($throwExceptions=false)
    {
        try {
            if ($this->is_active)
            {
                try
                {
                    $pl = $this->getList()->getPlugin();
                } catch (Exception $e) {
                    //plugin was disabled
                    $this->updateQuick('is_active', 0);
                    return $this;
                }
                if (!$pl->changeSubscription($this->getUser(), array(), array($this->getList()->plugin_list_id)))
                    return $this; // do not update active flag if failed (!)
            }
        } catch (Exception $e) {
            $this->getDi()->errorLogTable->log("EXCEPTION during unsubscribe user $this->user_id from list $this->list_id");
            $this->getDi()->errorLogTable->log($e);
            
            if($throwExceptions)
                throw $e;
            
            return $this;
        }
        $this->updateQuick('is_active', 0);
        return $this;
    }
    /** @return NewsletterList */
    function getList()
    {
        return $this->getDi()->newsletterListTable->load($this->list_id);
    }
    function getUser()
    {
        if (!$this->_user)
            $this->_user = $this->getDi()->userTable->load($this->user_id);
        return $this->_user;
    }
    function _setUser(User $user)
    {
        $this->_user = $user;
    }
    function unsubscribe($throwExceptions=false)
    {
        $this->disable($throwExceptions);
        $this->updateQuick('type', self::TYPE_UNSUBSCRIBED);
        return $this;
    }
    function isUnsubscribed()
    {
        return $this->type == self::TYPE_UNSUBSCRIBED;
    }
    function delete($throwExceptions=false)
    {
        $this->disable($throwExceptions);
        parent::delete();
    }
}

class NewsletterUserSubscriptionTable extends Am_Table
{
    protected $_key = 'subscription_id';
    protected $_table = '?_newsletter_user_subscription';
    
    /**
     * Add or enable subscription
     * @param type $user_id
     * @param type $list_id
     * @param type $type
     * @return type 
     */
    function add(User $user, NewsletterList $list, $type)
    {
        $list_id = $list->pk();
        $user_id = $user->pk();
        $sub = $this->findFirstBy(array(
            'user_id' => $user_id,
            'list_id' => $list_id, 
            ));
        if (!$sub) {
            $sub = $this->createRecord();
            $sub->user_id = $user_id;
            $sub->list_id = $list_id;
            $sub->is_active = 0;
            $sub->insert();
        }
        if(!empty($list->begin_date))
        {
            $sub->begin_date = $list->begin_date;
            $sub->expire_date = $list->expire_date;
        }
        $sub->enable($type);
        return $sub;
    }
    function checkSubscriptions(User $user)
    {
        if (!empty($user->unsubscribed))
        {
            foreach($this->findByUserId($user->pk()) as $sub) {
                $sub->unsubscribe();
            }
            return;
        }
        
        // array of NewsletterList user has access at all
        $ids = array();
        
        foreach ($this->getDi()->newsletterListTable->getAllowed($user) as $list)
        {
            $ids[ $list->pk() ] = array( 'l' => $list );
        }
        foreach ($this->findByUserId($user->pk()) as $r)
        {
            $ids[ $r->list_id]['s'] = $r;
        }
        
        ////
        foreach ($ids as $list_id => $record)
        {
            /* @var $availableList NewsletterList */
            if (empty($record['l'])) $record['l'] = null;
            if (empty($record['s'])) $record['s'] = null;
            $availableList = $record['l'];
            /* @var $existingSub NewsletterUserSubscription */
            $existingSub = $record['s'];
            
            if ($existingSub)
            {
                if (!$availableList) 
                {
                    // if not available now, de-activate
                    $existingSub->disable();
                    continue;
                } elseif ($existingSub->isUnsubscribed()) {
                    // if user unsubscribed previously, make sure it disabled
                    $existingSub->disable();
                    continue;
                } else  { // status = user or status = auto
                    // if user was subscribed before, enable it
                    $existingSub->enable();
                }
            } elseif ($user->data()->get(Bootstrap_Newsletter::NEWSLETTER_SIGNUP_DATA) == 1) {
                $this->add($user, $availableList, NewsletterUserSubscription::TYPE_USER);
            } elseif (($data = $user->data()->get(Bootstrap_Newsletter::NEWSLETTER_SIGNUP_DATA)) && 
                !empty($data[$availableList->pk()])) {
                $this->add($user, $availableList, NewsletterUserSubscription::TYPE_USER);
            } elseif ($availableList && $availableList->auto_subscribe) { // no existing list - create if 'auto'
                $this->add($user, $availableList, NewsletterUserSubscription::TYPE_AUTO);
            }
        }
    }
    /**
     * Return ids of lists user is enabled to receive, even if currently subscription is not available 
     * (say subscription expired)
     * @param type $user_id
     * @return type 
     */
    function getSubscribedIds($user_id)
    {
        return $this->_db->selectCol("SELECT list_id FROM $this->_table WHERE user_id=?d AND type <> ? AND is_active > 0", $user_id, 
            NewsletterUserSubscription::TYPE_UNSUBSCRIBED);
    }
    
    /**
     * Update list of subscriptions by admin - it does not check any permissions 
     * immediately, but subscriptions may be deleted during @link checkSubscriptions()
     */
    function adminSetIds($user_id, array $ids)
    {
        $user = $this->getDi()->userTable->load($user_id);
        $ids = array_filter(array_map('intval', $ids));
        $setSubs = array();
        foreach ($ids as $i)
            if ($i > 0)
            $setSubs[(int)$i] = array();

        $enabled = $disabled = array();
        foreach ($this->findByUserId($user_id) as $r)
            if ($r->is_active)
                $enabled[$r->list_id] = $r;
            else
                $disabled[$r->list_id] = $r;
        
        foreach (array_diff_key($enabled, $setSubs, $disabled) as $list_id => $sub)
        {
            if (!$sub->is_active) continue;
            $sub->_setUser($user);
            $sub->delete();
        }
        // 
        foreach (array_diff_key($setSubs, $enabled) as $list_id => $sub)
        {
            $list = $this->getDi()->newsletterListTable->load($list_id);
            $this->add($user, $list, NewsletterUserSubscription::TYPE_AUTO);
        }
        // enable disable subscriptions
        foreach (array_intersect_key($disabled, $setSubs) as $list_id => $sub)
        {
            $sub->enable();
        }
    }
}