#ifndef INCLUDED_HANDLER_
#define INCLUDED_HANDLER_

#include <iosfwd>
#include <string>
#include <vector>
#include <unordered_map>

#include "../types/types.h"
#include "../common/common.h"
#include "../utils/utils.h"
#include "../execnoio/execnoio.h"

#include "../zipcheck/zipcheck.h"

class Handler: private Types, private Utils, private Common
{
    using CCpair = std::pair<std::string, std::string>;

    enum MailType
    {
        EXERCISES,
        PUBLIC_KEY,
        PDF
    };

    ExecNoIO d_exec;

    std::string d_from;             // sender of the mail
    std::string d_zip;
    std::string d_date;

    std::string d_workingDir;

    std::string d_boundary;

    std::string d_set;
    std::string d_author;

    std::string d_rater;
    std::string d_raterDir;
    std::string d_raterEmail;

    std::string d_spoolZip;

    std::string d_pdfName;

    bool d_publicKey = false;
    bool d_debug = false;
    bool d_pdf2from = false;

    ZipCheck d_zipCheck;
                                            // key: abbreviation           
                                            // value: ratername, e-mail addr.
    using MapStrCCpair = std::unordered_map<std::string, CCpair>;

    MapStrCCpair d_ccInfo;

    public:
        Handler();
        ~Handler();

        void run();

    private:
        void fillCCinfo();
        void headers();
        void mailHeaders();
        void parseSpecs();

        void setRaterInfo();
        void setRaterInfo(MapStrCCpair::const_iterator const &iter);

        void rotate();                  // rotates rater-less sets over the
                                        // raters.

        void verifyAddress();
        void nextBoundary() const;      // find the next boundary
        void workingDir();

        void getTheZip();
        void setCCs();
        void saveZipFile();

        void saveZip(std::string &line);    
                                            
                                            // checks whether the attachment
        void saveTheZip(std::string const &line);   // has a .zip extension

        void saveSignature(std::string const &line);

        void inspectMetadata();
        static bool assign(std::string *dest, std::string const &regex, 
                                              std::string const &line);
        void publicKey() const;

        void compile();
        void compile(std::string const &source);

        void latexmk();
        void rmdir();

        void makePdf();
        void outputLatex();
        void filter(std::ostream &out, std::istream &in);

        void storeSpoolPath();              // store the result (pdf or zip)
                                            // in the spooldir

        void sections(std::ostream &out, std::string &line, 
                                         std::string const &key);
        static void replace(std::string &line, std::string const &target, 
                                           std::string const &replacement);

        void mail(MailType type);

        void mailZip() const;
};
        
#endif
