<?php

namespace Hwapx\Email;

require dirname(__FILE__). '/helpers/smtphelper.php';

use DB\SQL\Schema;
use HwapX\Core\Library\DB\SQL\Mapper;
use HwapX\Core\Library\Template;

use HwapX\Core\Library\Modulebase;

class Module extends Modulebase {
    const version = '1.0.0';

    public static $sidebar = array(
       'email' => array(
            'label' => 'Email',
            'icon' => 'envelope',
            array('icon' => 'envelope', 'label' => 'Contas', 'role' => 'hwapx.email.account_list', 'route' => 'admin_email_account_list'),
            array('icon' => 'pencil', 'label' => 'Template', 'role' => 'hwapx.email.template_list', 'route' => 'admin_email_template_list'),
            array('icon' => 'send', 'label' => 'Fila', 'role' => 'hwapx.email.queue_list', 'route' => 'admin_email_queue_list'),
        )
    );

    public static $roles = array(
        'template_create'     => 'Criar Template de Email',
        'template_edit'       => 'Editar Template de Email',
        'template_remove'     => 'Remover Template de Email',
        'template_list'       => 'Listar Template de Email',

        'account_create'     => 'Criar Conta de Email',
        'account_edit'       => 'Editar Conta de Email',
        'account_remove'     => 'Remover Conta de Email',
        'account_list'       => 'Listar Conta de Email',

        'queue_create'     => 'Criar Email na Fila',
        'queue_edit'       => 'Editar Email na Fila',
        'queue_remove'     => 'Remover Email na Fila',
        'queue_list'       => 'Listar Email na Fila',
        'queue_purge'      => 'Limpar Fila de Email',
    );

    protected $f3 = null;
    protected $db = null;

    public function __construct($f3) {
        $this->f3 = $f3;
        $this->db = $this->f3->get('db');
    }

    public function boot($f3) {
        \Cron::instance();
    }

    public function install() {
        $schema = new Schema($this->db);

        $table = $schema->createTable('hwapx_email_account');
        $table->addColumn('created_on')->type_datetime()->nullable(false);
        $table->addColumn('updated_on')->type_datetime()->nullable(false);
        $table->addColumn('created_by')->type_int()->nullable(true);
        $table->addColumn('updated_by')->type_int()->nullable(true);
        $table->addColumn('description')->type_varchar()->nullable(false);
        $table->addColumn('slug')->type_varchar()->nullable(false);
        $table->addColumn('email')->type_varchar()->nullable(false);
        $table->addColumn('password')->type_varchar()->nullable(false);
        $table->addColumn('server')->type_varchar()->nullable(false);
        $table->addColumn('port')->type_int()->nullable(false);
        $table->addColumn('mode')->type_varchar(3)->nullable(true);
        $table->build();

        $table = $schema->createTable('hwapx_email_template');
        $table->addColumn('created_on')->type_datetime()->nullable(false);
        $table->addColumn('updated_on')->type_datetime()->nullable(false);
        $table->addColumn('created_by')->type_int()->nullable(true);
        $table->addColumn('updated_by')->type_int()->nullable(true);
        $table->addColumn('description')->type_varchar()->nullable(false);
        $table->addColumn('slug')->type_varchar()->nullable(false);
        $table->addColumn('account_id')->type_int()->nullable(true);
        $table->addColumn('to')->type_varchar()->nullable(true);
        $table->addColumn('reply_to')->type_varchar()->nullable(true);
        $table->addColumn('from')->type_varchar()->nullable(true);
        $table->addColumn('subject')->type_varchar()->nullable(false);
        $table->addColumn('body')->type_text()->nullable(false);
        $table->build();

        $table = $schema->createTable('hwapx_email_queue');
        $table->addColumn('created_on')->type_datetime()->nullable(false);
        $table->addColumn('updated_on')->type_datetime()->nullable(false);
        $table->addColumn('created_by')->type_int()->nullable(true);
        $table->addColumn('updated_by')->type_int()->nullable(true);
        $table->addColumn('account_id')->type_int()->nullable(true);
        $table->addColumn('template_id')->type_int()->nullable(true);
        $table->addColumn('data')->type_text()->nullable(true);
        $table->addColumn('callback')->type_text()->nullable(true);
        $table->addColumn('to')->type_varchar()->nullable(false);
        $table->addColumn('reply_to')->type_varchar()->nullable(true);
        $table->addColumn('cc')->type_varchar()->nullable(true);
        $table->addColumn('bcc')->type_varchar()->nullable(true);
        $table->addColumn('subject')->type_varchar()->nullable(false);
        $table->addColumn('body')->type_text()->nullable(false);
        $table->addColumn('attachments')->type_text()->nullable(true);
        $table->addColumn('sent_at')->type_datetime()->nullable(true);
        $table->addColumn('log')->type_text()->nullable(true);
        $table->addColumn('cancelled_on')->type_datetime()->nullable(false);
        $table->addColumn('last_try')->type_datetime()->nullable(false);
        $table->build();
    }

    public function uninstall() {
        $schema = new Schema($this->db);

        $schema->dropTable('hwapx_email_queue');
        $schema->dropTable('hwapx_email_template');
        $schema->dropTable('hwapx_email_account');
    }

    public static function cron($f3) {
        $db       = $f3->get('db');
        $mapper   = new Mapper($db, 'hwapx_email_queue');
        $template = Template::instance();
        $steps    = $f3->get('email.steps', 4);
        $delay    = floor(40 / $steps);
        $rows     = $mapper->find(array('sent_at is null AND cancelled_on IS NULL AND failed = 0'), array('order' => 'id ASC', 'limit' => $steps));
        $count    = count($rows);

        foreach ($rows as $idx => $row) {
            $data = $row->data ? json_decode($row->data, true) : array();

            $row->executed_on = date('Y-m-d H:i:s');
            $row->save();

            if($row->callback) {
                $func   = $f3->grab($row->callback);
                $result = $func($f3, $data);

                if($result === false) {
                    $row->cancelled_on = date('Y-m-d H:i:s');
                    $row->save();
                    continue;
                }

                $row->callback_data = json_encode($result, JSON_PRETTY_PRINT);

                if(is_array($result))
                    $data = array_merge($data, $result);
            }

            $smtp = SMTPConnection($row->account_id);

            if($row->from)
                $smtp->set('From', $row->from);
            else
                $row->from = $smtp->get('From');

            $row->to_parsed = $template->resolve($row->to, $data);
            $row->subject_parsed = $template->resolve($row->subject, $data);

            $smtp->set('Content-Type', 'text/html; charset=utf-8;');
            $smtp->set('To', $row->to_parsed);
            $smtp->set('Subject', $row->subject_parsed);
            if($row->reply_to)
                $smtp->set('Reply-To', $template->resolve($row->reply_to, $data));
            if($row->cc)
                $smtp->set('CC', $row->cc);
            if($row->bcc)
                $smtp->set('BCC', $row->bcc);

            if($row->attachments)
                foreach (json_decode($row->attachments, true) as $alias => $attach) {
                    $args = is_array($attach) ? $attach : array($attach, $alias);
    
                    call_user_func_array(array($smtp, 'attach'), $args);
                }

            $row->body_parsed = $template->resolve($row->body, $data);

            if($row->track) {
                $tracker_url = $f3->get('SCHEME') . '://' . $f3->get('HOST') . $f3->get('BASE') . $f3->alias('api_email_tracker', $row->cast());
                $row->body_parsed .= "<img src=\"$tracker_url\" alt=\"Tracker pixel\">";
            }

            $row->save();

            $row->failed = $smtp->send($row->body_parsed, true) ? 0 : 1;

            if(!$row->failed) {
                $row->sent_at = date('Y-m-d H:i:s');
            }

            $row->log = $smtp->log();

            $row->save();

            $count--;

            if($count)
                sleep($delay);
        }
    }
}