#ifndef DOCCONVERT_H
#define DOCCONVERT_H


#include <map>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>


class DocConvert
{
public:
    //! originalKey is the key's original string with case preserved
    struct MetaValue { std::string originalKey; std::string value; };
    //! key in the map is in lowercase and trimmed whitespace
    using MetaDataType = std::map<std::string,MetaValue>;
    struct MetaData
    {
      void AddValue(std::string keyLower, std::string rawOriginalKey, std::string value)
      {
        insertionOrder.erase(std::remove(insertionOrder.begin(), insertionOrder.end(), keyLower), insertionOrder.end());
        insertionOrder.emplace_back(keyLower);
        map[keyLower] = MetaValue{ rawOriginalKey, value };
      }
      std::vector<std::string>  insertionOrder;
      MetaDataType              map;
    };

    DocConvert(void* error_handler = 0);
    ~DocConvert();

    void SetTitle(const char* title);
    void SetSource(const char* inFileName);
    void SetSourceData(const char* inData, size_t a_size);

    void Convert();

    void OutputHTML(const char* outFileName);
    void OutputPDF(const char* templateFileName, const char* outFileName, bool preview);

    // data is allocated
    void GetHTMLData(char** data, size_t* size);

    // data is not-allocated, you need to pass in and the size of it
    void GetPDFData(char* data, size_t* size);

    // access the meta-data
    const MetaData& GetMetaData() const { return m_metaData; }
    static int ExtractMetadataValues(size_t inputSiz, const char* inputData, MetaData& outputMetaData);

    static std::string CryptPassword(const std::string& pw);

    //void OutputBoth(const char* outFileNameHTML, const char* outFileNamePDF);
    //void ConvertToHTML(std::vector& outputData);
    //void ConvertToPDF(std::vector& outputData);

private:
    struct Pimpl;
    std::unique_ptr<Pimpl> m_pimpl;

    void ReplaceMetadata();
    MetaData m_metaData;
};


#endif // DOCCONVERT_H

