<?php
namespace MotoPlugin\MotoTeam\AdvancedContactForm;

use Moto;
use Zend;
use Website\Widgets;
use Zend\Stdlib\ArrayUtils;

class Service extends Moto\Service\AbstractStaticService
{
    const ERROR_UNABLE_TO_SEND_MESSAGE = 'COMMON.ERROR.UNABLE_TO_SEND';
    const ERROR_UNABLE_TO_SEND_CODE = 500;

    protected static $_mailSubject = 'New message from {{ WEBSITE.title }}';
    public static function sendMessage($message = null, $token = null)
    {
        if (Moto\Config::get('isDemoMode')) {
            return true;
        }

        $token = Moto\System::decrypt($token);

        if (!is_array($token) || empty($token['id']) || empty($token['hash'])) {
            throw new Moto\System\Exception(Moto\System\Exception::ERROR_BAD_REQUEST_MESSAGE, Moto\System\Exception::ERROR_BAD_REQUEST_CODE);
        }

        if (!Moto\System\Widgets\Storage::isExists($token['id'])) {
            throw new Moto\System\Exception(Moto\System\Exception::ERROR_BAD_REQUEST_MESSAGE, Moto\System\Exception::ERROR_BAD_REQUEST_CODE);
        }

        $formContent = Moto\System\Widgets\Storage::getById($token['id']);
        if (Moto\Util::getValue($formContent, 'hash') !== Moto\Util::getValue($token, 'hash')) {
            throw new Moto\System\Exception(Moto\System\Exception::ERROR_BAD_REQUEST_MESSAGE, Moto\System\Exception::ERROR_BAD_REQUEST_CODE);
        }

        $formFields = Moto\Util::getValue($formContent, 'properties._form_fields_');
        $recipient = Moto\Util::getValue($formContent, 'properties.settings.recipient', '');
        $recipient = trim($recipient);

        $render = Moto\Render::getInstance('string');
        $formFields = static::_reviveWidgets($formFields, $render);

        $inputFilter = Moto\InputFilter\Factory::create($formFields);
        $message = ArrayUtils::merge((array) $message, static::getRequest()->getFilesByParam('message'));
        $inputFilter->setData($message);

        if (!$inputFilter->isValid()) {
            throw new Moto\System\Exception(Moto\System\Exception::ERROR_BAD_REQUEST_MESSAGE, Moto\System\Exception::ERROR_BAD_REQUEST_CODE, $inputFilter->getMessagesKeys());
        }
        $message = $inputFilter->getValues();

        $data = array(
            'message' => static::_prepareMessage($message, $formFields, $render)
        );

        $subject = Moto\Util::getValue($formContent, 'properties.settings.subject');
        if ($subject === null) {
            $subject = $render->render(static::$_mailSubject, $data);
        }
        $body = $render->render(static::_getBodyTemplate(), $data);

        $params = array(
            'mailName' => 'contactForm',
            'subject' => $subject,
            'body' => $body,
            'attachments' => array(),
        );
        if (is_string($recipient) && $recipient !== '') {
            $recipient = str_replace("\n", ' ', $recipient);
            $params['to']['email'] = $recipient;
        }
        $fileFields = $inputFilter->getFileFields();
        if (is_array($fileFields) && count($fileFields) > 0) {
            foreach($fileFields as $fileField) {
                $files = Moto\Util::getValue($message, $fileField);
                if (!is_array($files) || empty($files)) {
                    continue;
                }
                if (array_key_exists('name', $files) || array_key_exists('path', $files) || array_key_exists('tmp_name', $files)) {
                    $files = [$files];
                }
                foreach($files as $file) {
                    if (!is_array($file)) {
                        continue;
                    }
                    if (empty($file['path'])) {
                        $file['path'] = $file['tmp_name'];
                    }
                    $params['attachments'][] = $file;
                }
            }
        }

        try {
            $result = Moto\Application\Util\Mailer::sendMail($params);
        } catch (\Exception $e) {
            Moto\System\Log::error(static::ERROR_UNABLE_TO_SEND_MESSAGE, array('exception_code' => $e->getCode(), 'exception_message' => $e->getMessage(), 'message' => $message, 'user' => static::_getSenderDetails()));
            throw new Moto\System\Exception(static::ERROR_UNABLE_TO_SEND_MESSAGE, static::ERROR_UNABLE_TO_SEND_CODE);
        }

        if (count($params['attachments']) > 0) {
            foreach($params['attachments'] as $file) {
                if (file_exists($file['tmp_name'])) {
                    @unlink($file['tmp_name']);
                }
            }
        }

        return $result;
    }
    protected static function _reviveWidgets($fields)
    {
        foreach ($fields as $i => $field) {
            if (empty($field['widget'])) {
                continue;
            }
            $widget = Moto\System\Widgets\Factory::create($field['widget']);
            if ($widget) {
                $fields[$i]['widget'] = $widget;
            }
        }

        return $fields;
    }
    protected static function _prepareMessage($request, $fields, $renderEngine)
    {
        $result = array();
        foreach ($fields as $field) {
            if (empty($field['name'])) {
                continue;
            }
            $name = $field['name'];
            if (!array_key_exists($name, $request)) {
                continue;
            }
            $input = Moto\System\Widgets\Factory::create($field['widget']);
            if (!$input) {
                $input = new Widgets\FormElements\MessageField();
                $input->setFieldName($name);
            } else {
                $input->setRenderEngine($renderEngine);
            }
            $input->setFieldValue($request[$name]);
            $result[$name] = $input;
        }

        return $result;
    }
    protected static function _getBodyTemplate()
    {
        $template = '';
        $file = __DIR__ . '/../templates/message_body.html.twig';
        if (file_exists($file)) {
            $template = file_get_contents($file);
        }

        return $template;
    }
    protected static function _getSenderDetails()
    {
        $data = array(
            'browser' => (empty($_SERVER['HTTP_USER_AGENT']) ? null : $_SERVER['HTTP_USER_AGENT']),
            'ip' => (empty($_SERVER['REMOTE_ADDR']) ? null : $_SERVER['REMOTE_ADDR']),
            'referrer' => (empty($_SERVER['HTTP_REFERER']) ? null : $_SERVER['HTTP_REFERER']),
        );

        return $data;
    }
}
