<?php

namespace HS\IncomingMail\Processors;

use Illuminate\Support\Arr;
use HS\IncomingMail\Message;
use UserScape_Bayesian_Classifier;

class Spam
{
    /**
     * @var Message
     */
    private $message;

    public function __construct(Message $message)
    {
        $this->message = $message;
    }

    /**
     * The Spam check, this goes through
     * allow list, deny list, then finally the bayesian check.
     * @return bool
     */
    public function isSpam()
    {
        if ($this->isAllowListed(hs_setting('cHD_SPAM_WHITELIST'))) {
            return false;
        }

        if ($this->isDenyListed(hs_setting('cHD_SPAM_BLACKLIST'))) {
            return true;
        }

        return $this->isBayesianSpam();
    }

    /**
     * Is it spam according to the bayesian check.
     * @return bool
     */
    public function isBayesianSpam()
    {
        if (hs_setting('cHD_SPAMFILTER') == 0) { // if it's not turned on then bail out.
            return false;
        }

        $spamText['subject'] = $this->message->getSubject();
        $spamText['from'] = $this->message->getFromName();
        $spamText['body'] = $this->message->getParsedBody();
        $spamText['headers'] = $this->message->getFromEmail();

        $spamCheck = new UserScape_Bayesian_Classifier($spamText);
        if ($spamCheck->Check() === '-1') {
            return true;
        }
        return false;
    }

    /**
     * @param string $denylist
     * @return bool
     */
    public function isDenyListed($denylist = '')
    {
        return $this->validateAgainstHeaders($denylist);
    }

    /**
     * @param string $allowlist
     * @return bool
     */
    public function isAllowListed($allowlist = '')
    {
        return $this->validateAgainstHeaders($allowlist);
    }

    /**
     * Search the headers for a string
     *
     * @param $list
     * @return bool
     */
    protected function validateAgainstHeaders($list)
    {
        if (hs_empty($list)) {
            return false;
        }

        $patterns = explode("\n", $list);
        $headers = implode("\n", Arr::flatten($this->message->headers));
        foreach ($patterns as $pattern) {
            $pattern = trim($pattern);
            if (! empty($pattern) && stripos($headers, $pattern) !== false) {
                return true;
            }
        }

        return false;
    }
}
