<?php
/**
 * @author  Immerce GmbH
 * @package Immerce_Email
 * @license https://opensource.org/licenses/GPL-3.0
 */
namespace Immerce\Email\Plugin\Framework\Mail\Template;

use Magento\Framework\Mail\Address;
use Magento\Framework\Mail\MimePart;
use Magento\Framework\Mail\Template\TransportBuilder as MageTransportBuilder;
use Zend\Mail\Header\HeaderWrap;

class TransportBuilder
{
    /**
     * @param MageTransportBuilder $subject
     * @param mixed $address
     * @param string $name
     * @return array
     * @see \Magento\Framework\Mail\Template\TransportBuilder::addTo()
     */
    public function beforeAddTo(MageTransportBuilder $subject, $address, $name = '')
    {
        if (is_array($address)) {
            $this->encodeAdressArray($address);
        }

        return [$address, $this->encodeString($name)];
    }

    /**
     * @param MageTransportBuilder $subject
     * @param mixed $address
     * @param string $name
     * @return array
     * @see \Magento\Framework\Mail\Template\TransportBuilder::addCc()
     */
    public function beforeAddCc(MageTransportBuilder $subject, $address, $name = '')
    {
        if (is_array($address)) {
            $this->encodeAdressArray($address);
        }

        return [$address, $this->encodeString($name)];
    }

    /**
     * @param MageTransportBuilder $subject
     * @param mixed $email
     * @param null $name
     * @return array
     * @see \Magento\Framework\Mail\Template\TransportBuilder::setReplyTo()
     */
    public function beforeSetReplyTo(MageTransportBuilder $subject, $email, $name = null)
    {
        if (is_array($email)) {
            $this->encodeAdressArray($email);
        }

        return [$email, $name !== null ? $this->encodeString($name) : $name];
    }

    /**
     * @param MageTransportBuilder $subject
     * @param mixed $address
     * @return array
     * @see \Magento\Framework\Mail\Template\TransportBuilder::addBcc()
     */
    public function beforeAddBcc(MageTransportBuilder $subject, $address)
    {
        if (is_array($address)) {
            $this->encodeAdressArray($address);
        }

        return [$address];
    }

    /**
     * @param string $input
     * @return string
     */
    protected function encodeString(string $input)
    {
        return HeaderWrap::canBeEncoded($input) ? HeaderWrap::mimeEncodeValue($input, MimePart::CHARSET_UTF8) : $input;
    }

    /**
     * @param array $addresses
     * @return void
     */
    protected function encodeAdressArray(array $addresses)
    {
        foreach ($addresses as $address) {
            if ($address instanceof Address) {
                $name = $this->encodeString($address->getName());
                $mail = $address->getEmail();
                $address->__construct($mail, $name);
            }
        }
    }
}
