#pragma once
#include <util/generic/string.h>
#include <util/system/shellcommand.h>
#include <util/system/hostname.h>
#include <util/charset/utf8.h>
#include <library/cpp/charset/wide.h>
#include <library/cpp/mediator/messenger.h>
#include <library/cpp/logger/global/global.h>

namespace NRTY {

    class TMailInfoMessage : public IMessage {
    private:
        TString MainAddresses;
        TString CopyAddresses;
        TString Subject;
        TString Data;
        TString ContentType;

        void Encode(TString& str) {
            if (!IsUtf(str))
                str = WideToUTF8(CharToWide(str, csYandex));
        }

        void Encode() {
            Encode(Subject);
            Encode(Data);
        }
    public:
        TMailInfoMessage(const TString& main, const TString& data, const TString& subject) {
            MainAddresses = main;
            Subject = subject;
            Data = data;
            ContentType = "text/plain";
            Encode();
        }

        TMailInfoMessage(const TString& main, const TString& copy, const TString& data, const TString& subject) {
            MainAddresses = main;
            CopyAddresses = copy;
            Subject = subject;
            Data = data;
            ContentType = "text/plain";
            Encode();
        }

        TMailInfoMessage(const TString& main, const TString& copy, const TString& data, const TString& subject, const TString& contentType) {
            MainAddresses = main;
            CopyAddresses = copy;
            Subject = subject;
            Data = data;
            ContentType = contentType;
            Encode();
        }

        const TString& GetMainAddresses() const {
            return MainAddresses;
        }

        const TString& GetContentType() const {
            return ContentType;
        }

        const TString& GetCopyAddresses() const {
            return CopyAddresses;
        }

        const TString& GetSubject() const {
            return Subject;
        }

        const TString& GetData() const {
            return Data;
        }
    };

    class TMailService : public IMessageProcessor {
    private:
    public:
        TMailService() {
            RegisterGlobalMessageProcessor(this);
        }

        ~TMailService() {
            UnregisterGlobalMessageProcessor(this);
        }

        virtual bool Process(IMessage* message) {
            TMailInfoMessage* messMail = dynamic_cast<TMailInfoMessage*>(message);
            if (messMail) {
                INFO_LOG << "SUBJECT:\n" << messMail->GetSubject() << "\nDATA:\n" << messMail->GetData() << Endl;
                if (!!messMail->GetMainAddresses()) {
                    try {
                        TShellCommandOptions options;
                        options.SetClearSignalMask(true);
                        options.SetCloseAllFdsOnExec(true);
                        TShellCommand cmd("echo '" + messMail->GetData() + "\n-------------------------------\n" + HostName() + "' | mail -s \"" + messMail->GetSubject() + "\" -a \"Content-type: " + messMail->GetContentType() + "; charset=UTF-8\" -c \"" + messMail->GetCopyAddresses() + "\" " + messMail->GetMainAddresses(), options);
                        cmd.Run();
                        cmd.Wait();
                        if (cmd.GetStatus() == TShellCommand::SHELL_INTERNAL_ERROR) {
                            ERROR_LOG << "Can't sent mail: " << cmd.GetInternalError() << Endl;
                        } else if (cmd.GetStatus() == TShellCommand::SHELL_ERROR) {
                            ERROR_LOG << "Can't sent mail: " << cmd.GetError() << Endl;
                        } else if (cmd.GetStatus() == TShellCommand::SHELL_FINISHED) {
                        } else {
                            ERROR_LOG << "Can't sent mail: incorrect status: " << (ui32)cmd.GetStatus() << Endl;
                        }
                    }
                    catch (...) {
                        ERROR_LOG << "Can't sent mail: error: " << CurrentExceptionMessage() << Endl;
                    }
                }
                return true;
            }
            return false;
        }

        virtual TString Name() const {
            return "TMailService";
        }
    };
}
