<?php

if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

use PHPMailer\PHPMailer\PHPMailer;

/**
 * Library for sending mail with admin part which includes settings
 */
class Emailmng
{

    const SMTP_PROTOCOL     = 'smtp';
    const MAIL_PROTOCOL     = 'mail';
    const SENDMAIL_PROTOCOL = 'sendmail';
    const SMTP_PORT         = '25';
    const DEFAULT_MAIL_TYPE = '1';
    const DEFAULT_PRIORITY  = '3';
    const DEFAULT_WRAPCHARS = '76';

    protected $email;
    protected $template_data;
    protected $CI;
    protected $default_config = [
        'protocol'     => self::SENDMAIL_PROTOCOL,
        'charset'      => 'utf8',
        'mailtype'     => self::DEFAULT_MAIL_TYPE,
        'sender_email' => 'test@email.test',
        'sender_name'  => 'test',
        'wordwrap' => true,
        'priority' => self::DEFAULT_PRIORITY
    ];

    public function __construct()
    {
        $this->CI    = & get_instance();
        $this->email = new PHPMailer();
        $this->initialize();
    }

    /**
     * Magic function call for class Email
     * @param string $method
     * @param array $arguments
     * @return type
     */
    public function __call($method = '', $arguments = [])
    {
        if (method_exists($this->email, $method)) {

            return call_user_func_array([$this->email, $method], $arguments);
        } else {
            show_error('The ' . $method . ' does not exist!');
        }
    }

    /**
     * Initialize preferences
     * @param array $config
     * @return $this
     */
    public function initialize($config = [])
    {
        $cnf = array_merge($this->get_config(), $config);
        if (!empty($cnf['sender_email'])) {
            $this->email->setFrom($cnf['sender_email'], $cnf['sender_name']);
        }
        if ($cnf['protocol'] == self::SMTP_PROTOCOL) {
            $this->email->isSMTP();
            $this->email->Host       = $cnf['smtp_host'];
            $this->email->SMTPAuth   = true;
            $this->email->Username   = $cnf['smtp_user'];
            $this->email->Password   = $cnf['smtp_pass'];
            $this->email->SMTPSecure = $cnf['smtp_crypto'];
            $this->email->Port       = $cnf['smtp_port'];
        } elseif ($cnf['protocol'] == self::SENDMAIL_PROTOCOL) {
            $this->email->isSendmail();
        } else {
            $this->email->isMail();
        }
        $this->email->CharSet = $cnf['charset'];
        $this->email->WordWrap = $cnf['wordwrap'] ? $cnf['wrapchars'] : 0;
        $this->email->isHTML(($cnf['mailtype'] == self::DEFAULT_MAIL_TYPE));
        $this->email->Priority = $cnf['priority'];

        return $this;
    }
    
    /**
     * Set to
     * @param string $email
     * @param string $name
     * @return $this
     */
    public function to($email, $name = '')
    {
        $this->email->clearAddresses();
        $this->email->addAddress($email, $name);
        
        return $this;
    }
    
    /**
     * Set email message
     * @param string $message
     * @param string $alt_message
     * @return $this
     */
    public function message($message, $alt_message = '')
    {
        $this->email->Body = $message;
        if (!empty($alt_message)) {
            $this->email->AltBody = strip_tags($message);
        }
        
        return $this;
    }

    /**
     * Prepare and send new template
     * $args - parameters to replace patterns in template
     * @param string $code
     * @param array $args
     * @return $this
     */
    public function send_template($code, $subject_args = [], $message_args = [])
    {
        $this->CI->load->library('parser');
        $this->CI->load->model('emailmng/template_tmodel');
        $template_data = $this->CI->template_tmodel->fetch_by_code($code);
        if ($template_data) {
            $this->email->isHTML(($template_data['mailtype'] == self::DEFAULT_MAIL_TYPE));
            $parser               = new CI_Parser();
            $parser->set_delimiters('[[', ']]');
            $this->email->Subject = $parser->parse_string($template_data['subject'], $subject_args, true);
            $message              = $parser->parse_string($template_data['message'], $message_args, true);
            $alt_message = ($template_data['mailtype'] == self::DEFAULT_MAIL_TYPE) ? strip_tags($message) : '';
            $this->message($message, $alt_message);

            if (!empty($template_data['copy_to'])) {
                $this->email->addCC($template_data['copy_to']);
            }

            if (!empty($template_data['hidden_copy_to'])) {
                $this->email->addBCC($template_data['hidden_copy_to']);
            }

            $status = $this->send();
            if (!$status) {
                log_message('error', 'Mailer Error: ' . $this->email->ErrorInfo);
            }

            return $status;
        } else {

            return false;
        }
    }

    /**
     * Send email
     * @return boolean
     */
    public function send()
    {
        return $this->email->send();
    }

    /**
     * Prepare configuration for sending mail
     * @return array
     */
    protected function get_config()
    {
        $this->CI->load->library('ciext/configurator');
        $conf = new configurator('emailmng');
        $data = $conf->get_config();

        if (!isset($data['protocol'])) {
            return $this->default_config;
        }

        $config = [];
        if ($data['protocol'] == self::SMTP_PROTOCOL) {
            $config['protocol']    = self::SMTP_PROTOCOL;
            $config['smtp_host']   = str_replace(['ssl://', 'tls://'], '', $data['smtp_host']);
            $config['smtp_user']   = $data['smtp_user'];
            $config['smtp_pass']   = $data['smtp_pass'];
            $config['smtp_port']   = !empty($data['smtp_port']) ? $data['smtp_port'] : self::SMTP_PORT;
            $config['smtp_crypto'] = empty($data['smtp_crypto']) ? 'ssl' : $data['smtp_crypto'];
        } else {
            $config['protocol'] = $data['protocol'];
        }
        $config['charset']   = 'utf-8';
        $config['wordwrap']  = ($data['wordwrap']) ? true : false;
        $config['mailtype']  = $data['mailtype'];
        $config['priority']  = (!empty($data['priority'])) ? $data['priority'] : self::DEFAULT_PRIORITY;
        $config['wrapchars'] = !empty($data['wrapchars']) ? $data['wrapchars'] : self::DEFAULT_WRAPCHARS;
        if (!empty($data['sender_email'])) {
            $config['sender_email'] = $data['sender_email'];
            $config['sender_name']  = $data['sender_name'];
        } else {
            $sys_conf = new configurator('ciext');
            if (!empty($sys_conf->item('email_from'))) {
                $config['sender_email'] = $sys_conf->item('email_from');
            }
        }

        return $config;
    }

}
