<?php

/*
 * @component UserPoints
 * @copyright Copyright (C) 2015-2022 Bernard Gilly - Adrien Roussel - Martin Brampton
 * @license : GNU/GPL
 * @Website : https://remository.com
 */

namespace BlackSheepResearch\Component\UserPoints\Site\Controllers;

// no direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Mail\MailHelper;
use Joomla\Utilities\IpHelper;
use BlackSheepResearch\Component\UserPoints\Site\UserController;
use BlackSheepResearch\Component\UserPoints\Site\UserPoints;
use BlackSheepResearch\Component\UserPoints\Site\Problems\PointsDetails;
use BlackSheepResearch\Component\UserPoints\Site\Problems\TemplateInvitation;
use BlackSheepResearch\Component\UserPoints\Site\Problems\User;
use BlackSheepResearch\Component\UserPoints\Site\Problems\Invitation;

/**
 * @package UserPoints
 */
class InviteControl extends UserController {

    protected $app = null;

    public function display($cachable = false, $urlparams = false) {
        $view = $this->getView('Invite', 'html');
        $view->display();
    }

    public function referral() {
        $referrerid = $this->input->get('referrerid', '', 'username');
        if ($referrerid) {
            Factory::getApplication()->setUserState('com_userpoints.referral', $referrerid);
        }
        $this->redirect(Invitation::makeRegistrationLink());
    }

    public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true)) {
        $return = parent::getModel($name, $prefix, array('ignore_request' => false));
        return $return;
    }

    /* public function _display($cachable = false, $urlparams = false)
      {


      $user =  UserPoints::getUser();
      if ( $user->id )
      $user_name = $user->name;
      else
      $user_name = "";

      $model      = $this->getModel ( 'invite' );
      $view       = $this->getView  ( 'invite','html' );

      $referrerid = $model->_getReferreid();
      $params 	= $model->_getParamsAUP();

      $cparams = ComponentHelper::getParams( 'com_userpoints' );

      if ( $referrerid )
      $referrer_link = getLinkToInvite( $referrerid, $cparams->get('systemregistration') );
      else
      $referrer_link = getLinkToInvite( '', $cparams->get('systemregistration') );

      //$this->viewdata['model'] = $model ; //?
      $this->viewdata['params'] = $params ;
      $this->viewdata['user_name'] = $user_name ;
      $this->viewdata['referreid'] = $referrerid ;
      $this->viewdata['referrer_link'] = $referrer_link ;

      // Display
      if ( Factory::getApplication()->input->get('task', '', 'cmd')=='addressbook')
      $view->_display_addressbook();
      else
      $view->display();

      } */

    public function sendinvite() {

        $app = Factory::getApplication();
        $this->checkToken('request', true);

        $model = $this->getModel('invite');
        $view = $this->getView('invite', 'html');
        $data = $this->input->post->get('jform', array(), 'array');

        $other_emails = $data['other_recipients'];
        $sender = $data['sender'];
        $custommessage = $data['custommessage'];
        $cparams = ComponentHelper::getParams('com_userpoints');

        $params = $model->_getParamsAUP();

        $form = $model->getForm();
        if (!$form) {
            $app->enqueueMessage($model->getError(), 'error');
            return false;
        }

        $validate = $model->validate($form, $data);
        if ($validate === false) {
            // Get the validation messages.
            $errors = $model->getErrors();
            // Push up to three validation messages out to the user.
            for ($i = 0, $n = count($errors); $i < $n && $i < 5; $i++) {
                if ($errors[$i] instanceof Exception) {
                    $app->enqueueMessage($errors[$i]->getMessage(), 'warning');
                } else {
                    $app->enqueueMessage($errors[$i], 'warning');
                }
            }
            // Save the data in the session.
            $app->setUserState('com_userpoints.invite.data', $data);
            // Redirect back to the form.
            $this->redirect('index.php?option=com_userpoints&view=invite&Itemid=' . $app->input->getInt('Itemid'), false);
            return false;
        }

        // active user
        $user = UserPoints::getUser();

        $SiteName = $app->getCfg('sitename');
        $MailFrom = $app->getCfg('mailfrom');
        $FromName = $app->getCfg('fromname');

        $now = TemplateInvitation::datetimeSQL();

        $link = Invitation::makeReferralLink($app->input->post->get('referreid', '', 'username'));

        // An array of e-mail headers we do not want to allow as input
        $headers = array('Content-Type:',
            'MIME-Version:',
            'Content-Transfer-Encoding:',
            'bcc:',
            'cc:');

        // An array of the input fields to scan for injected headers
        $fields = array('mailto',
            'sender',
            'from',
            'subject',
        );

        /*
         * Here is the meat and potatoes of the header injection test.  We
         * iterate over the array of form input and check for header strings.
         * If we find one, send an unauthorized header and die.
         */
        foreach ($fields as $field) {
            foreach ($headers as $header) {
                if (strpos(@$_POST[$field], $header) !== false) {
                    $app->enqueueMessage('Err0r', 'error');
                }
            }
        }

        /*
         * Free up memory
         */
        unset($headers, $fields);

        $imported_emails = $this->input->post->get('importedemails', '', 'string');

        // Check for a valid to address
        $errorMail = false;

        // build list emails
        if ($imported_emails == '' && $other_emails != '') {
            $emails = $other_emails;
        } elseif ($other_emails == '' && $imported_emails != '') {
            $emails = $imported_emails;
        } elseif ($imported_emails != '' && $other_emails != '') {
            $emails = $imported_emails . "," . $other_emails;
        } else {
            $emails = "";
            $errorMail = Text::_('AUP_EMAIL_INVALID');
            $app->enqueueMessage($errorMail, 'warning');
        }

        $emails = explode(',', $emails);

        // Check for a valid from address
        if (!$MailFrom || !MailHelper::isEmailAddress($MailFrom)) {
            $errorMail = Text::sprintf('AUP_EMAIL_INVALID', $MailFrom);
            $app->enqueueMessage($errorMail, 'warning');
        }

        if ($errorMail) {
            return $this->display();
        }

        // Build the message to send
        $msg = Text::_('AUP_EMAIL_MSG_INVITE');

        $formatMail = false;
        $bcc2admin = false;

        if ($params->get('templateinvite', 0)) {
            $row = new TemplateInvitation(intval($params->get('templateinvite', 0)));
            $subject = $row->emailsubject;
            $markers = ['{name}', '{custom}', '{link}'];
            $substitutes = [$sender, $custommessage, $link];
            $body = str_replace($markers, $substitutes, $row->emailbody);
            $bcc2admin = (bool) $row->bcc2admin;
            $formatMail = (bool) $row->emailformat;
        } else {
            $subject = Text::_('AUP_YOUAREINVITEDTOREGISTERON') . " " . $SiteName;
            $body = sprintf($msg, $SiteName, $sender, $link) . " \n" . $custommessage;
        }

        // Clean the email data
        $subject = MailHelper::cleanSubject($subject);
        $body = MailHelper::cleanBody($body);

        // Limit
        $max = $params->get('maxemailperinvite', 1);
        $maxperday = $params->get('maxinvitesperday', 1);
        $delay = intval($params->get('delaybetweeninvites', 0));

        $counter = 0;

        $refer_ID = UserPoints::getAnyUserReferreID($user->id);

        $numpoints4invite = UserPoints::getPointsRule('sysplgup_invite');
        $totalpointsearned = 0;

        $currentmaxperday = $model->_checkCurrentMaxPerDay('sysplgup_invite', $refer_ID, IpHelper::getIp());

        $checkdelay = 1;
        if ($delay) {
            $checkdelay = $model->_checkLastInviteForDelay('sysplgup_invite', $refer_ID, IpHelper::getIp(), $delay);
        }

        if (!$checkdelay) {
            $errorTime = Text::_('AUP_DELAY_BETWEEN_INVITES_INVALID');
            $app->enqueueMessage($errorTime, 'warning');
            return $this->display();
        }

        if ($currentmaxperday < $maxperday) {

            foreach ($emails as $email) {
                $aEmails[0] = $model->_extractEmailsFromString($email);
                $email = $aEmails[0][0];
                if (MailHelper::isEmailAddress($email) AND User::sendEmail($email, $subject, $body, $formatMail, $bcc2admin) === true) {
                    if ($user->id) {
                        if (UserPoints::checkRuleEnabled('sysplgup_invite')) {
                            // insert email for tracking
                            $email2 = str_replace("@", " [at] ", $email); // change @ because can be display on frontend in latest activity
                            $keyreference = UserPoints::buildKeyreference('sysplgup_invite', $email);
                            UserPoints::userpoints('sysplgup_invite', $refer_ID, 0, $keyreference, $email2);
                            $totalpointsearned = $totalpointsearned + $numpoints4invite;
                        }
                    } else {
                        // guest user : Insert IP and email fortracking
                        $detail = new PointsDetails();
                        $detail->referreid = 'GUEST';
                        $detail->points = 0;
                        $detail->insert_date = $now;
                        $detail->expire_date = '';
                        $detail->rule_id = 'sysplgup_invite';
                        $detail->approved = 1;
                        $detail->status = 1;
                        $detail->keyreference = IpHelper::getIp();
                        $detail->datareference = $email;
                        $detail->enabled = 1;
                        $detail->save();
                    }
                    $counter++;
                    $currentmaxperday++;
                }
                if ($counter == $max || $currentmaxperday == $maxperday) {
                    break;
                }
            }
            if ($totalpointsearned) {
                if ($totalpointsearned > 1) {
                    $msg = sprintf(Text::_('AUP_CONGRATULATIONS_PLURAL'), $totalpointsearned);
                } else {
                    $msg = sprintf(Text::_('AUP_CONGRATULATIONS_SINGULAR'), $totalpointsearned);
                }
                $app->enqueueMessage($msg, 'message');
            }
        } else {
            $maxperdaylimit = Text::_('AUP_MAXINVITESPERDAY') . " " . $maxperday;
            $app->enqueueMessage($maxperdaylimit, 'message');
        }

        switch ($counter) {
            case '0':
                $message = Text::_('AUP_NO_EMAIL_HAS_BEEN_SENT');
                break;
            case '1':
                $message = Text::_('AUP_EMAIL_SENT');
                break;
            default:
                $message = sprintf(Text::_('AUP_EMAILS_SENT'), $counter);
                break;
        }

        $app->enqueueMessage($message, 'message');
        $this->redirect('index.php?option=com_userpoints&view=invite&Itemid=' . $app->input->getInt('Itemid'), false);
    }
}
