settings = $this->email->email_object->settings;
        $this->setLocale()
             ->setFrom()
             ->setTo()
             ->setCc()
             ->setTemplate()
             ->setBody()
             ->setSubject()
             ->setReplyTo()
             ->setBcc()
             ->setAttachments()
             ->setVariables()
             ->setHeaders();
        return $this->email->email_object;
    }
    /**
     * Sets the locale
     */
    private function setLocale(): self
    {
        if ($this->email->email_object->client) {
            $this->locale = $this->email->email_object->client->locale();
        } elseif ($this->email->email_object->vendor) {
            $this->locale = $this->email->email_object->vendor->locale();
        } else {
            $this->locale = $this->email->company->locale();
        }
        App::setLocale($this->locale);
        App::forgetInstance('translator');
        $t = app('translator');
        $t->replace(Ninja::transformTranslations($this->settings));
        return $this;
    }
    /**
     * Sets the template
     */
    private function setTemplate(): self
    {
        $this->template = $this->email->email_object->settings->email_style;
        match ($this->email->email_object->settings->email_style) {
            'plain' => $this->template = 'email.template.plain',
            'light' => $this->template = 'email.template.client',
            'dark' => $this->template = 'email.template.client',
            'custom' => $this->template = 'email.template.custom',
            default => $this->template = 'email.template.client',
        };
        $this->email->email_object->html_template = $this->template;
        return $this;
    }
    /**
     * Sets the FROM address
     */
    private function setFrom(): self
    {
        if (Ninja::isHosted() && in_array($this->email->email_object->settings->email_sending_method,['default', 'mailgun'])) {
            if ($this->email->company->account->isPaid() && property_exists($this->email->email_object->settings, 'email_from_name') && strlen($this->email->email_object->settings->email_from_name) > 1) {
                $email_from_name = $this->email->email_object->settings->email_from_name;
            } else {
                $email_from_name = $this->email->company->present()->name();
            }
            $this->email->email_object->from = new Address(config('mail.from.address'), $email_from_name);
            return $this;
        }
        if ($this->email->email_object->from) {
            return $this;
        }
        $this->email->email_object->from = new Address(config('mail.from.address'), config('mail.from.name'));
        return $this;
    }
    /**
     * Sets the To address
     */
    private function setTo(): self
    {
        if ($this->email->email_object->to) {
            return $this;
        }
        $this->email->email_object->to = [new Address($this->email->email_object->contact->email, $this->email->email_object->contact->present()->name())];
        return $this;
    }
    /**
     * Sets the body of the email
     */
    private function setBody(): self
    {
        if (strlen($this->email->email_object->body) > 3) {
            // A Custom Message has been set in the email screen.
        } elseif (strlen($this->email->email_object->settings?->{$this->email->email_object->email_template_body}) > 3) {
            // A body has been saved in the settings.
            $this->email->email_object->body = $this->email->email_object->settings?->{$this->email->email_object->email_template_body};
        } else {
            // Default template to be used
            $this->email->email_object->body = EmailTemplateDefaults::getDefaultTemplate($this->email->email_object->email_template_body, $this->locale);
        }
        $breaks = ["
","
","
"];
        $this->email->email_object->text_body = str_ireplace($breaks, "\r\n", $this->email->email_object->body);
        $this->email->email_object->text_body = strip_tags($this->email->email_object->text_body);
        $this->email->email_object->text_body = str_replace(['$view_button','$viewButton'], '$view_url', $this->email->email_object->text_body);
        if ($this->template == 'email.template.custom') {
            $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, str_replace(["\r","\n"], "", $this->email->email_object->settings->email_style_custom)));
        }
        return $this;
    }
    /**
     * Sets the subject of the email
     */
    private function setSubject(): self
    {
        if ($this->email->email_object->subject) { //where the user updates the subject from the UI
            return $this;
        } elseif (strlen($this->email->email_object->settings?->{$this->email->email_object->email_template_subject}) > 3) {
            $this->email->email_object->subject = $this->email->email_object->settings?->{$this->email->email_object->email_template_subject};
        } else {
            $this->email->email_object->subject = EmailTemplateDefaults::getDefaultTemplate($this->email->email_object->email_template_subject, $this->locale);
        }
        return $this;
    }
    /**
     * Sets the reply to of the email
     */
    private function setReplyTo(): self
    {
        $reply_to_email = $this->email->company->owner()->email;
        $reply_to_name = $this->email->company->owner()->present()->name();
        if(str_contains($this->email->email_object->settings->reply_to_email, "@")) {
            $reply_to_email = $this->email->email_object->settings->reply_to_email;
        } elseif(isset($this->email->email_object->invitation->user)) {
            $reply_to_email = $this->email->email_object->invitation->user->email;
        }
        if(strlen($this->email->email_object->settings->reply_to_name) > 3) {
            $reply_to_name = $this->email->email_object->settings->reply_to_name;
        } elseif(isset($this->email->email_object->invitation->user)) {
            $reply_to_name = $this->email->email_object->invitation->user->present()->name();
        }
        $this->email->email_object->reply_to = array_merge($this->email->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);
        return $this;
    }
    /**
     * Replaces the template placeholders
     * with variable values.
     */
    public function setVariables(): self
    {
        $this->email->email_object->body = strtr($this->email->email_object->body, $this->email->email_object->variables);
        $this->email->email_object->text_body = strtr($this->email->email_object->text_body, $this->email->email_object->variables);
        $this->email->email_object->subject = strtr($this->email->email_object->subject, $this->email->email_object->variables);
        //06-06-2023 ensure we do not parse markdown in custom templates
        if ($this->template != 'custom' && $this->template != 'email.template.custom') {
            $this->email->email_object->body = $this->parseMarkdownToHtml($this->email->email_object->body);
        }
        return $this;
    }
    /**
     * Sets the BCC of the email
     */
    private function setBcc(): self
    {
        $bccs = [];
        $bcc_array = [];
        if (strlen($this->email->email_object->settings->bcc_email) > 1) {
            if (Ninja::isHosted() && $this->email->company->account->isPaid()) {
                $bccs = array_slice(explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)), 0, 5);
            } else {
                $bccs = (explode(',', str_replace(' ', '', $this->email->email_object->settings->bcc_email)));
            }
        }
        foreach ($bccs as $bcc) {
            $bcc_array[] = new Address($bcc);
        }
        $this->email->email_object->bcc = array_merge($this->email->email_object->bcc, $bcc_array);
        return $this;
    }
    /**
     * Sets the CC of the email
     */
    private function setCc(): self
    {
        return $this;
        // return $this->email->email_object->cc;
        // return [
        // ];
    }
    /**
     * Sets the attachments for the email
     *
     * Note that we base64 encode these, as they
     * sometimes may not survive serialization.
     *
     * We decode these in the Mailable later
     */
    private function setAttachments(): self
    {
        $documents = [];
        /* Return early if the user cannot attach documents */
        if (!$this->email->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT) || $this->email->email_object->email_template_subject == 'email_subject_statement') {
            return $this;
        }
        /** Purchase Order / Invoice / Credit / Quote PDF  */
        if ($this->email->email_object->settings->pdf_email_attachment) {
            $pdf = ((new CreateRawPdf($this->email->email_object->invitation))->handle());
            $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($pdf), 'name' => $this->email->email_object->entity->numberFormatter().'.pdf']]);
        }
        /** UBL xml file */
        if ($this->email->email_object->settings->ubl_email_attachment && $this->email->email_object->entity instanceof Invoice) {
            $ubl_string = (new CreateUbl($this->email->email_object->entity))->handle();
            if ($ubl_string) {
                $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($ubl_string), 'name' => $this->email->email_object->entity->getFileName('xml')]]);
            }
        }
        /** E-Invoice xml file */
        if ($this->email->email_object->settings->enable_e_invoice && ! $this->email->email_object->entity instanceof PurchaseOrder) {
            $xml_string = $this->email->email_object->entity->service()->getEInvoice();
            if($xml_string) {
                $this->email->email_object->attachments = array_merge($this->email->email_object->attachments, [['file' => base64_encode($xml_string), 'name' => explode(".", $this->email->email_object->entity->getFileName('xml'))[0]."-e_invoice.xml"]]);
            }
        }
        if (!$this->email->email_object->settings->document_email_attachment || !$this->email->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
            return $this;
        }
        /* Company Documents */
        $this->email->email_object->documents = array_merge($this->email->email_object->documents, $this->email->company->documents()->where('is_public', true)->pluck('id')->toArray());
        /** Entity Documents */
        if ($this->email->email_object->entity?->documents) {
            $this->email->email_object->documents = array_merge($this->email->email_object->documents, $this->email->email_object->entity->documents()->where('is_public', true)->pluck('id')->toArray());
        }
        /** Recurring Invoice Documents */
        if ($this->email->email_object->entity instanceof Invoice && $this->email->email_object->entity->recurring_id != null) {
            $this->email->email_object->documents = array_merge($this->email->email_object->documents, $this->email->email_object->entity->recurring_invoice->documents()->where('is_public', true)->pluck('id')->toArray());
        }
        /** Task / Expense Documents */
        if ($this->email->email_object->entity instanceof Invoice) {
            $expense_ids = [];
            $task_ids = [];
            foreach ($this->email->email_object->entity->line_items as $item) {
                if (property_exists($item, 'expense_id')) {
                    $expense_ids[] = $item->expense_id;
                }
                if (property_exists($item, 'task_id')) {
                    $task_ids[] = $item->task_id;
                }
            }
            if (count($expense_ids) > 0) {
                Expense::query()->whereIn('id', $this->transformKeys($expense_ids))
                        ->where('invoice_documents', 1)
                        ->cursor()
                        ->each(function ($expense) {
                            $this->email->email_object->documents = array_merge($this->email->email_object->documents, $expense->documents()->where('is_public', true)->pluck('id')->toArray());
                        });
            }
            if (count($task_ids) > 0 && $this->email->company->invoice_task_documents) {
                Task::query()->whereIn('id', $this->transformKeys($task_ids))
                    ->cursor()
                    ->each(function ($task) {
                        $this->email->email_object->documents = array_merge($this->email->email_object->documents, $task->documents()->where('is_public', true)->pluck('id')->toArray());
                    });
            }
        }
        return $this;
    }
    /**
     * Sets the headers for the email
     */
    private function setHeaders(): self
    {
        if ($this->email->email_object->invitation_key) {
            $this->email->email_object->headers = array_merge($this->email->email_object->headers, ['x-invitation' => $this->email->email_object->invitation_key]);
        }
        return $this;
    }
    /**
     * Converts any markdown to HTML in the email
     *
     * @param  string $markdown The body to convert
     * @return string           The parsed markdown response
     */
    private function parseMarkdownToHtml(string $markdown): ?string
    {
        $converter = new CommonMarkConverter([
            'allow_unsafe_links' => false,
        ]);
        return $converter->convert($markdown);
    }
}