<?php
require_once 'modules/clients/models/user.php';
require_once 'newedge/classes/NE_MailGateway.php';
require_once 'modules/admin/models/ServicePlugin.php';
// require_once 'modules/clients/models/Client_EventLog.php';
require_once 'modules/support/models/AutoresponderTemplateGateway.php';
require_once 'modules/clients/models/UserPackageGateway.php';
require_once 'modules/admin/models/Package.php';

/**
* @package Plugins
*/
class PluginAutomailer extends ServicePlugin
{
    function getVariables()
    {
        $variables = array(
            /*T*/'Plugin Name'/*/T*/   => array(
                'type'          => 'hidden',
                'description'   => /*T*/''/*/T*/,
                'value'         => /*T*/'Auto Mailer'/*/T*/,
            ),
            /*T*/'Enabled'/*/T*/       => array(
                'type'          => 'yesno',
                'description'   => /*T*/'When enabled, email customers a set number of days before/after a given event.<br><b>NOTE:</b> Only run once per day to avoid duplicate E-mails.'/*/T*/,
                'value'         => '0',
            ),
            /*T*/'Events'/*/T*/       => array(
                'type'        => 'custom',
                'description' => /*T*/'List of the events that will send emails to your customers.<br>The email templates are of type \'Custom E-Mails\' and you can add more on <a href="index.php?fuse=admin&view=Admin_Emails&settings=mail"><b><u>E-Mail - Templates</u></b></a> and then select \'Custom E-Mails\'. Available tags for the email template are: [BILLINGEMAIL], [SUPPORTEMAIL], [COMPANYNAME], [COMPANYADDRESS], [COMPANYURL], [CLIENTAPPLICATIONURL], [CLIENTNAME], [FIRSTNAME], [CLIENTEMAIL], [ORGANIZATION], [PACKAGEGROUPNAME], [PLANNAME], [PACKAGEID], [NEXTDUEDATE], [FORGOTPASSWORDURL]'/*/T*/,
                'method'      => 'eventsGrid',    // This property only works for 'type' => 'custom'
                'value'       => ''
            ),
            /*T*/'Summary E-mail'/*/T*/     => array(
                'type'          => 'smallTextarea',
                'description'   => /*T*/'E-mail addresses to which a summary of each service run will be sent.  (Leave blank if you do not wish to receive a summary)'/*/T*/,
                'value'         => '',
            ),
            /*T*/'Summary E-mail Subject'/*/T*/     => array(
                'type'          => 'text',
                'description'   => /*T*/'E-mail subject for the summary notification.'/*/T*/,
                'value'         => 'Auto Mailer Summary',
            ),
            /*T*/'Run schedule - Minute'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '0',
                'helpid'        => '8',
            ),
            /*T*/'Run schedule - Hour'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '0',
            ),
            /*T*/'Run schedule - Day'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '*',
            ),
            /*T*/'Run schedule - Month'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '*',
            ),
            /*T*/'Run schedule - Day of the week'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number in range 0-6 (0 is Sunday) or a 3 letter shortcut (e.g. sun)'/*/T*/,
                'value'         => '*',
            ),
        );

        return $variables;
    }

    function execute()
    {
        parent::execute();

        $messages = array();
        $numCustomers = 0;
        $mailGateway = new NE_MailGateway();

        // Summary Variables
        $summaryNames = array();
        $summaryErrors = array();

        // Required Services
        $requiredServices = array();

        /*
        Get the params:
          - Email template (from custom emails. will display the template name, but will use the template id)
          - Number of days before/after the date (an integer number)
          - Event:
              'After Account Activated'
              'After Account Canceled'
              'After Package Activated'
              'After Package Canceled'
              'Before Domain Expires'
              'Before Hosting Package Due Date'
              'Before Domain Package Due Date'
              'Before SSL Package Due Date'
              'Before General Package Due Date'

          For example:
            37 (Are you enjoying our application?)      $AutomailerRule['templateid']
            5                                           $AutomailerRule['days']
            After Account Activated                     $AutomailerRule['event']
        */
        $AutomailerRules = @htmlspecialchars_decode($this->settings->get('plugin_automailer_Events'), ENT_QUOTES);

        if($AutomailerRules == ''){
            array_unshift($messages, $this->user->lang('%s customer(s) were notified.', $numCustomers));
            return $messages;
        }
        $AutomailerRules = unserialize($AutomailerRules);
        if(!is_array($AutomailerRules)){
            array_unshift($messages, $this->user->lang('%s customer(s) were notified.', $numCustomers));
            return $messages;
        }

        //Get the customers for each case:
        foreach($AutomailerRules as $AutomailerRule){
            switch($AutomailerRule['event']){
                // Before Dates
                case 'Before Domain Expires':
                case 'Before Hosting Package Due Date':
                case 'Before Domain Package Due Date':
                case 'Before SSL Package Due Date':
                case 'Before General Package Due Date':
                    $dateTimeStamp = mktime(0, 0, 0, date("m"), date("d") + $AutomailerRule['days'], date("Y"));
                    break;

                // After Dates
                case 'After Account Activated':
                case 'After Account Canceled':
                case 'After Package Activated':
                case 'After Package Canceled':
                default:
                    $dateTimeStamp = mktime(0, 0, 0, date("m"), date("d") - $AutomailerRule['days'], date("Y"));
                    break;
            }

            switch($AutomailerRule['event']){
                case 'After Account Activated':
                    $query = "SELECT u.`id` AS customer_id "
                            ."FROM `users` u "
                            ."JOIN `user_customuserfields` ucuf "
                            ."ON u.`id` = ucuf.`userid` "
                            ."WHERE u.`groupid` = 1 "
                            ."AND u.`status` IN (".USER_STATUS_ACTIVE.") "
                            ."AND ucuf.`customid` IN ( "
                            ."SELECT cuf.`id` "
                            ."FROM `customuserfields` cuf "
                            ."WHERE cuf.`name` = 'Last Status Date' "
                            ."AND cuf.`type` = 52 AND cuf.company_id=?) "
                            ."AND (UNIX_TIMESTAMP(ucuf.`value`) >= ?) "
                            ."AND (UNIX_TIMESTAMP(ucuf.`value`) < ?) ";
                    $result = $this->db->query($query, NE_Registry::getCompany()->getId(), $dateTimeStamp, $dateTimeStamp + 86400);
                    break;
                case 'After Account Canceled':  // Includes Canceled and Inactive Users
                    $query = "SELECT u.`id` AS customer_id "
                            ."FROM `users` u "
                            ."JOIN `user_customuserfields` ucuf "
                            ."ON u.`id` = ucuf.`userid` "
                            ."WHERE u.`groupid` = 1 "
                            ."AND u.`status` IN (".USER_STATUS_INACTIVE.", ".USER_STATUS_CANCELLED.") "
                            ."AND ucuf.`customid` IN ( "
                            ."SELECT cuf.`id` "
                            ."FROM `customuserfields` cuf "
                            ."WHERE cuf.`name` = 'Last Status Date' "
                            ."AND cuf.`type` = 52 AND cuf.company_id=?) "
                            ."AND (UNIX_TIMESTAMP(ucuf.`value`) >= ?) "
                            ."AND (UNIX_TIMESTAMP(ucuf.`value`) < ?) ";
                    $result = $this->db->query($query, NE_Registry::getCompany()->getId(), $dateTimeStamp, $dateTimeStamp + 86400);
                    break;
                case 'After Package Activated':
                    $query = "SELECT DISTINCT u.`id` AS customer_id, d.`id` AS package_id "
                            ."FROM `users` u "
                            ."JOIN `domains` d "
                            ."ON u.`id` = d.`CustomerID` "
                            ."JOIN `object_customField` ocf "
                            ."ON d.`id` = ocf.`objectid` "
                            ."WHERE d.`status` IN (".PACKAGE_STATUS_ACTIVE.") "
                            ."AND ocf.`customFieldId` IN ( "
                            ."SELECT cf.`id` "
                            ."FROM `customField` cf "
                            ."WHERE cf.`name` = 'Last Status Date' "
                            ."AND cf.`groupId` = 2) "
                            ."AND (UNIX_TIMESTAMP(ocf.`value`) >= ?) "
                            ."AND (UNIX_TIMESTAMP(ocf.`value`) < ?) ";

                    $result = $this->db->query($query, $dateTimeStamp, $dateTimeStamp + 86400);
                    break;
                case 'After Package Canceled':  // Includes Canceled, Suspended, and Expired Packages
                    $query = "SELECT DISTINCT u.`id` AS customer_id, d.`id` AS package_id "
                            ."FROM `users` u "
                            ."JOIN `domains` d "
                            ."ON u.`id` = d.`CustomerID` "
                            ."JOIN `object_customField` ocf "
                            ."ON d.`id` = ocf.`objectid` "
                            ."WHERE d.`status` IN (".PACKAGE_STATUS_SUSPENDED.", ".PACKAGE_STATUS_CANCELLED.", ".PACKAGE_STATUS_EXPIRED.") "
                            ."AND ocf.`customFieldId` IN ( "
                            ."SELECT cf.`id` "
                            ."FROM `customField` cf "
                            ."WHERE cf.`name` = 'Last Status Date' "
                            ."AND cf.`groupId` = 2) "
                            ."AND (UNIX_TIMESTAMP(ocf.`value`) >= ?) "
                            ."AND (UNIX_TIMESTAMP(ocf.`value`) < ?) ";
                    $result = $this->db->query($query, $dateTimeStamp, $dateTimeStamp + 86400);
                    break;
                case 'Before Domain Expires':  // Includes Active and Pending Cancellation Packages
                    // Query based on the custom field "Expiration Date".  The field value is timestamp type.
                    $query = "SELECT DISTINCT u.`id` AS customer_id, d.`id` AS package_id "
                            ."FROM `users` u "
                            ."JOIN `domains` d "
                            ."ON u.`id` = d.`CustomerID` "
                            ."JOIN `object_customField` ocf "
                            ."ON d.`id` = ocf.`objectid` "
                            ."WHERE d.`status` IN (".PACKAGE_STATUS_ACTIVE.", ".PACKAGE_STATUS_PENDINGCANCELLATION.") "
                            ."AND d.`Plan` IN ( "
                            ."SELECT pa.`id` "
                            ."FROM `package` pa "
                            ."WHERE pa.`planid` IN ( "
                            ."SELECT pr.`id` "
                            ."FROM `promotion` pr "
                            ."WHERE pr.`type` = 3)) "
                            ."AND ocf.`customFieldId` IN ( "
                            ."SELECT cf.`id` "
                            ."FROM `customField` cf "
                            ."WHERE cf.`name` = 'Expiration Date' "
                            ."AND cf.`groupId` = 2 "
                            ."AND cf.`subGroupId` = 3) "
                            ."AND ocf.`value` >= ? "
                            ."AND ocf.`value` < ? ";
                    $result = $this->db->query($query, $dateTimeStamp, $dateTimeStamp + 86400);

                    // Requires "Domain Updater" Service
                    $requiredServices[] = 'domainupdater';
                    break;
                case 'Before Hosting Package Due Date':
                case 'Before Domain Package Due Date':
                case 'Before SSL Package Due Date':
                case 'Before General Package Due Date':
                    $packageTypeId = 0;
                    switch($AutomailerRule['event']){
                        case 'Before Hosting Package Due Date':
                            $packageTypeId = 1;
                            break;
                        case 'Before Domain Package Due Date':
                            $packageTypeId = 3;
                            break;
                        case 'Before SSL Package Due Date':
                            $packageTypeId = 2;
                            break;
                        case 'Before General Package Due Date':
                            $packageTypeId = 0;
                            break;
                    }

                    // Query based on the "nextbilldate" field of the "recurringfee" table.
                    $query = "SELECT DISTINCT u.`id` AS customer_id, d.`id` AS package_id "
                            ."FROM `users` u "
                            ."JOIN `domains` d "
                            ."ON u.`id` = d.`CustomerID` "
                            ."JOIN `recurringfee` rf "
                            ."ON d.`id` = rf.`appliestoid` "
                            ."AND rf.`billingtypeid` = -1 "
                            ."AND rf.`recurring` = 1 "
                            ."AND rf.paymentterm != 0 "
                            ."WHERE d.`status` IN (".PACKAGE_STATUS_ACTIVE.", ".PACKAGE_STATUS_PENDINGCANCELLATION.") "
                            ."AND d.`Plan` IN ( "
                            ."SELECT pa.`id` "
                            ."FROM `package` pa "
                            ."WHERE pa.`planid` IN ( "
                            ."SELECT pr.`id` "
                            ."FROM `promotion` pr "
                            ."WHERE pr.`type` = $packageTypeId)) "
                            ."AND (UNIX_TIMESTAMP(rf.`nextbilldate`) >= ?) "
                            ."AND (UNIX_TIMESTAMP(rf.`nextbilldate`) < ?) ";
                    $result = $this->db->query($query, $dateTimeStamp, $dateTimeStamp + 86400);
                    break;
                default:
                    continue;
                    break;
            }

            // If find customers:
            if($result->getNumRows()){
                // - Setup the customer email template
                $templategateway = new AutoresponderTemplateGateway();
                $template = $templategateway->getAutoresponder($AutomailerRule['templateid']);

                if($template->getId() != $AutomailerRule['templateid']){
                    $summaryErrors[] = $AutomailerRule['templateid'];
                }else{
                    $strEmailArrT = $template->getContents(true);
                    $strSubjectEmailT = $template->getSubject();
                    $strNameEmailT = $template->getName();

                    // - For each customer:
                    while($row = $result->fetch()){
                        // * Instantiate the user
                        $user = new User($row['customer_id']);

                        // * Create a copy of the email template
                        $strEmailArr     = $strEmailArrT;
                        $strSubjectEmail = $strSubjectEmailT;

                        // * Parse a copy of the email template and the email subject template
                        if(isset($row['package_id'])){
                            $userPackage = new UserPackage((int)$row['package_id']);
                            $package = new Package($userPackage->Plan);

                            $gateway = new UserPackageGateway($this->user);

                            $strSubjectEmail = $gateway->_replaceTags1($strSubjectEmail,$user,$package);
                            $strEmailArr = array(
                                'HTML'      => $gateway->_replaceTags1($strEmailArr['HTML'], $user, $package),
                                'plainText' => $gateway->_replaceTags1($strEmailArr['plainText'],$user,$package)
                            );

                            $gateway->_replaceTagsByType($userPackage,$user,$strEmailArr, $strSubjectEmail);


                            $additionalEmailTags = array(
                                "[PACKAGEGROUPNAME]" => $package->productGroup->fields['name'],
                                "[PACKAGEID]"        => $row['package_id'],
                                "[NEXTDUEDATE]"      => date($this->settings->get('Date Format'), $dateTimeStamp),
                                "[BILLINGEMAIL]"     => $this->settings->get("Billing E-mail")
                            );
                            $strSubjectEmail = str_replace(array_keys($additionalEmailTags), $additionalEmailTags, $strSubjectEmail);
                            $strEmailArr = array(
                                'HTML'      => str_replace(array_keys($additionalEmailTags), $additionalEmailTags, $strEmailArr['HTML']),
                                'plainText' => str_replace(array_keys($additionalEmailTags), $additionalEmailTags, $strEmailArr['plainText'])
                            );
                        }else{
                            $gateway = new UserPackageGateway($this->user);

                            $strSubjectEmail = $gateway->_replaceTags1($strSubjectEmail,$user);
                            $strEmailArr = array(
                                'HTML'      => $gateway->_replaceTags1($strEmailArr['HTML'], $user),
                                'plainText' => $gateway->_replaceTags1($strEmailArr['plainText'],$user)
                            );
                        }

                        // * Send a parsed copy of the email template to the customer
                        $mailerResult = $mailGateway->mailMessage(
                            $strEmailArr,
                            $this->settings->get('Support E-mail'),
                            $this->settings->get('Company Name'),
                            $row['customer_id'],
                            "",
                            $strSubjectEmail,
                            3,
                            0,
                            'notifications',
                            '',
                            '',
                            $user->isHTMLMails()? MAILGATEWAY_CONTENTTYPE_HTML : MAILGATEWAY_CONTENTTYPE_PLAINTEXT
                        );

                        if(!is_a($mailerResult, 'NE_Error')){
// log the email was sent

/*
$clientLog = Client_EventLog::newInstance(false, $row['customer_id'], $row['customer_id'], CLIENT_EVENTLOG_SENTUPCOMINGCHARGENOTIFICATION, $this->user->getId(), $batchAmount);
$this->logger->addEventLog($clientLog);
*/
                        }

                        // * Add Customer to summary
                        $summaryNames[$strNameEmailT][$AutomailerRule['days']][$AutomailerRule['event']][] = $user->getFullName().((isset($row['package_id']))? ', package: '.$row['package_id'] : '');
                        $numCustomers++;
                    }
                }
            }
        }

        if($this->settings->get('plugin_automailer_Summary E-mail') != ""){
            $summaryEmail = '';
            if(count($requiredServices) > 0){
                $summaryEmailRequirementsIssues = array();
                $summaryEmailRequirementsTime = array();
                foreach($requiredServices as $requiredService){
                    // Get the Service name
                    $requiredServiceName = $this->settings->get('plugin_'.$requiredService.'_Plugin Name');
                    if(!$requiredServiceName){
                        $requiredServiceName = $requiredService;
                    }

                    // Verify if the Service is enabled
                    if(!$this->settings->get('plugin_'.$requiredService.'_Enabled')){
                        $summaryEmailRequirementsIssues[] = $this->user->lang("The service %s is not enabled", $requiredServiceName);
                    }else{
                        // Verify the last time the Service ran
                        $requiredServiceInfo = $this->settings->get('service_'.$requiredService.'_info');
                        if(!$requiredServiceInfo){
                            $summaryEmailRequirementsIssues[] = $this->user->lang("The service %s do not have information about its last run.", $requiredServiceName);
                        }else{
                            $requiredServiceInfo = unserialize($requiredServiceInfo);
                            if(!is_array($requiredServiceInfo) || !isset($requiredServiceInfo['time'])){
                                $summaryEmailRequirementsIssues[] = $this->user->lang("The information of the service %s about its last run, seems to be corrupted.", $requiredServiceName);
                            }else{
                                $summaryEmailRequirementsTime[$requiredServiceName] = $requiredServiceInfo['time'];
                            }
                        }
                    }
                }
                if (count($summaryEmailRequirementsIssues) > 0) {
                    $summaryEmail .= $this->user->lang("Auto Mailer has detected issues with some of the required Services for the Events selected. Please take a look").":\n";

                    foreach($summaryEmailRequirementsIssues as $summaryEmailRequirementsIssue){
                        $summaryEmail .= " - ".$summaryEmailRequirementsIssue."\n";
                    }
                    $summaryEmail .= "\n";
                }
                if (count($summaryEmailRequirementsTime) > 0) {
                    $summaryEmail .= $this->user->lang("Last execution of the required Services for the Events selected, were").":\n";

                    foreach($summaryEmailRequirementsTime as $summaryEmailRequirementName => $summaryEmailRequirementTime){
                        $summaryEmail .= " - ".$summaryEmailRequirementName.". Executed on: ".$summaryEmailRequirementTime."\n";
                    }
                    $summaryEmail .= "\n";
                }
            }


            if (count($summaryErrors) > 0) {
                $summaryEmail .= $this->user->lang("Auto Mailer has not been able to find the E-mail Templates with the following ids. Please take a look").":\n";

                foreach($summaryErrors as $summaryError){
                    $summaryEmail .= " - ".$summaryError."\n";
                }
                $summaryEmail .= "\n";
            }

            if(count($summaryNames) > 0){
                $summaryEmail .= $this->user->lang("Auto Mailer has emailed the following events to the following customers").":\n";

                foreach($summaryNames as $emailTemplateName => $summaryDays){
                    foreach($summaryDays as $days => $summaryEvent){
                        foreach($summaryEvent as $event => $summaryCustomers){
                            $summaryEmail .= "\n".'"'.$emailTemplateName.'" emailed '.$days.' days '.$event.":\n";

                            foreach($summaryCustomers as $summaryCustomer){
                                $summaryEmail .= " - ".$summaryCustomer."\n";
                            }
                        }
                    }
                }
            }

            if($summaryEmail != ''){
                $destinataries = explode("\r\n", $this->settings->get('plugin_automailer_Summary E-mail'));

                foreach($destinataries as $destinatary){
                    $mailGateway->mailMessageEmail(
                        $summaryEmail,
                        $this->settings->get('Support E-mail'),
                        $this->settings->get('Company Name'),
                        $destinatary,
                        "",
                        $this->settings->get('plugin_automailer_Summary E-mail Subject')
                    );
                }
            }
        }

        array_unshift($messages, $this->user->lang('%s customer(s) were notified.', $numCustomers));
        return $messages;
    }

    /**
     *
     * @param type $tplView
     */
    function eventsGrid($tplView,$settingConfig,$user)
    {
        //here we create our stores
        //and just pass them to our own template to build our grid

        $tplView->settingId = $settingConfig['id']; //needs to have the setting id here


        $settingConfig['value'] = @htmlspecialchars_decode($settingConfig['value'], ENT_QUOTES);
        $gridDataArray = array();
        if($settingConfig['value'] != ''){
            $settingConfig['value'] = unserialize($settingConfig['value']);
            foreach($settingConfig['value'] AS $gridRow){
                //you need to store template name with the setting config
                $gridDataArray[] = "['".implode("', '", $gridRow)."']";
            }
        }
        $tplView->gridData = "[".implode(", ", $gridDataArray)."]";
        $tplView->emailTemplates = $this->createOptionsObject($this->getEmailTemplates());
        $tplView->productEvents  = $this->createOptionsObject($this->getPackageEvents());
        return $tplView->fetch('/plugins/services/automailer/PluginAutomailer.tpl.php');
    }

    function getEmailTemplates()
    {
        $values = array();

        $query = "SELECT `id`, `name` "
                ."FROM `autoresponders` "
                ."WHERE `type` = 2 ";
        $result = $this->db->query($query);

        while(list($templateid, $templatename) = $result->fetch()){
            $values[] = array($templateid, $templatename);
        }

        return $values;
    }

    function getPackageEvents()
    {
        $values = array(
            array('After Account Activated'        , 'After Account Activated'        ),
            array('After Account Canceled'         , 'After Account Canceled'         ),
            array('After Package Activated'        , 'After Package Activated'        ),
            array('After Package Canceled'         , 'After Package Canceled'         ),
            array('Before Domain Expires'          , 'Before Domain Expires'          ),
            array('Before Hosting Package Due Date', 'Before Hosting Package Due Date'),
            array('Before Domain Package Due Date' , 'Before Domain Package Due Date' ),
            array('Before SSL Package Due Date'    , 'Before SSL Package Due Date'    ),
            array('Before General Package Due Date', 'Before General Package Due Date')
        );
        return $values;
    }

    function createOptionsObject($fieldValues){
        $storeArray = array();
        if(is_array($fieldValues)){
            foreach($fieldValues as $fieldValue){
                $storeArray[] = "['".implode("', '", $fieldValue)."']";
            }
        }
        return "[".implode(", ", $storeArray)."]";
    }
}
?>
