<?php

namespace WPDesk\Library\WPEmail;

use WPDesk\Library\WPEmail\Abstracts\EmailInterface;
use WPDesk\Library\WPEmail\Parser\HTMLDecorator;
use WPDesk\View\Renderer\Renderer;
use WPDesk\View\Renderer\SimplePhpRenderer;
use WPDesk\View\Resolver\ChainResolver;
use WPDesk\View\Resolver\DirResolver;
use WPDesk\View\Resolver\WPThemeResolver;

class EmailSender {

    /**
     * @var EmailInterface[]
     */
    private $emails = [];

    /**
     * @var string
     */
    private $from = 'wordpress@wordpress.org';

    /**
     * @var string
     */
    private $from_name = 'WordPress';

    /**
     * @var Renderer
     */
    private $renderer;

    /**
     * @param $from
     * @param $from_name
     */
    public function __construct() {
        $this->init_renderer();
    }

    public function init_renderer() {
        $resolver = new ChainResolver();
        $resolver->appendResolver( new DirResolver( __DIR__ ) );

        $this->renderer = new SimplePhpRenderer( $resolver );
    }

    public function set_renderer( Renderer $renderer ) {
        $this->renderer = $renderer;
    }

    public function add_email( EmailInterface $email ) {
        $this->emails[ $email->get_id() ] = $email;
    }

    public function get_emails(): array {
        return $this->emails;
    }

    public function set_from( string $from ) {
        $this->from = $from;
    }


    /**
     * WordPress callback for setting the from email
     *
     * @param string $email
     *
     * @return string
     */
    public function from( $email ): string {
        if ( ! empty( $this->from ) && is_email( $this->from ) ) {
            $email = $this->from;
        }

        return $email;
    }


    public function set_from_name( string $from_name ) {
        $this->from_name = $from_name;
    }


    /**
     * WordPress callback for setting the from name
     *
     * @param string $name
     *
     * @return string
     */
    public function from_name( $name ) {
        if ( ! empty( $this->from_name ) ) {
            $name = html_entity_decode( sanitize_text_field( $this->from_name ) );
        }

        return $name;
    }

    /**
     * Add filters before fire wp_mail.
     *
     * @return void
     */
    private function before_wp_mail() {
        add_filter( 'wp_mail_from', array( $this, 'from' ) );
        add_filter( 'wp_mail_from_name', array( $this, 'from_name' ) );
    }

    public function send( array $placeholders = [] ) {
        foreach ( $this->get_emails() as $email ) {
            $template = $this->get_template( $email, $placeholders );
            if ( $email->get_is_enable() ) {
                $this->before_wp_mail();
                wp_mail(
                    $email->get_recipients(), $email->get_subject(), $this->css_inline( $template ), $email->get_headers(), $email->get_attachments()
                );
                $this->after_wp_mail();
            }
        }
    }

    public function get_template( EmailInterface $email, $placeholders = [] ): string {
        $content = $this->replace_placeholders( $email->get_content(), $placeholders );
        $output  = $this->renderer->render( 'html/email-header', [] );
        $output  .= $this->renderer->render( 'html/' . $email->get_id(), [ 'content' => $content ] );
        $output  .= $this->renderer->render( 'html/email-footer', [] );

        return $output;
    }

    /**
     * @param string $content
     * @param array  $placeholders
     *
     * @return array|string|string[]
     */
    private function replace_placeholders( string $content, array $placeholders = [] ): string {
        return str_replace( array_keys( $placeholders ), array_values( $placeholders ), $content );
    }

    /**
     * @param string $content
     *
     * @return mixed|string
     */
    private function css_inline( string $content ): string {
        $styles = $this->renderer->render( 'html/styles', [] );
        $body   = HTMLDecorator::style_inline( $content, $styles );
    }

    /**
     * Remove filters after fire wp_mail.
     *
     * @return void
     */
    private function after_wp_mail() {
        remove_filter( 'wp_mail_from', array( $this, 'from' ) );
        remove_filter( 'wp_mail_from_name', array( $this, 'from_name' ) );
    }

}