#ifndef SIGN_UTIL_H
#define SIGN_UTIL_H
#include <string>
#include <map>
#include <vector>

namespace rtx
{
    namespace common
    {

        namespace constants
        {
            const std::string LF = "\n";
            const std::string SPE1 = ",";
            const std::string SPE2 = ":";
        }

        namespace systemHeader
        {
            const std::string X_CA_SIGNATURE = "X-CA-SIGNATURE";
            const std::string X_CA_SIGNATURE_HEADERS = "X-CA-SIGNATURE-HEADERS";
            const std::string X_CA_KEY = "x-ca-key";
            const std::string X_CA_NONCE = "x-ca-nonce";
            const std::string X_CA_TIMESTAMP = "x-ca-timestamp";

            const std::string HTTP_HEADER_ACCEPT = "Accept";
            const std::string HTTP_HEADER_CONTENT_TYPE = "Content-Type";
            const std::string HTTP_HEADER_DATE = "Date";

            const std::string DATE = "Date";
        }

        class HttpMethod
        {
        public:
            static const HttpMethod POST_BODY;

            const std::string value;
            const std::string requestContentType;
            const std::string acceptContentType;

        private:
            HttpMethod(const std::string &v, const std::string &r, const std::string &a)
                : value(v), requestContentType(r), acceptContentType(a) {}
        };

        namespace signUtil
        {
            bool checkSign(const std::string &secret,
                           const std::map<std::string, std::string> &headers,
                           const std::string &uri,
                           const std::string &bodys);

            std::string sign(HttpMethod httpMethod,
                             const std::string &secret,
                             const std::map<std::string, std::string> &headers,
                             const std::string &uri,
                             const std::string &bodys);

            std::string buildStringToSign(HttpMethod httpMethod,
                                          const std::map<std::string, std::string> &headers,
                                          const std::string &uri,
                                          const std::string &bodys);

            std::string getHttpDateHeaderValue(const std::map<std::string, std::string> &headers);

            std::string contentMd5(const std::string &bodys);

            std::string bytesToHex(const unsigned char* bytes, size_t length);

            std::string md5HexString(const std::string &content);

            std::string headersStr(const std::map<std::string, std::string> &headers);

            std::string generateRandomString();

            std::string generateUuid();
        }

        namespace encryptUtil
        {
            std::string encrypt(const std::string &plaintext,
                const std::string &key,
                const std::string &iv);

                std::string decrypt(const std::string &ciphertext_base64,
                    const std::string &key,
                    const std::string &iv);
        }
    } // namespace Common
}
#endif // SIGN_UTIL_H