#include "pch.h"
#include "WebAppCore/Http/HttpContext.h"
#include "System/Console.h"
#include "System/Convert.h"
#include <string>

namespace DotNetDupe {
    namespace WebAppCore {
        namespace Http {

            static void WriteRaw(System::SmartPointer<System::Net::Sockets::NetworkStream> pStream, const std::string& str) {
                if (!pStream.IsNull() && !str.empty()) {
                    pStream->Write(str.data(), 0, static_cast<int>(str.length()));
                }
            }

            static std::string GetHttpStatusMessage(int code) {
                switch (code) {
                case 201: return "Created";
                case 204: return "No Content";
                case 400: return "Bad Request";
                case 401: return "Unauthorized";
                case 404: return "Not Found";
                case 500: return "Internal Server Error";
                default: return "OK";
                }
            }

            static std::string BuildResponseHeaderString(int statusCode, const System::String& contentType, bool bChunked, const System::Collections::Generic::Dictionary<System::String, System::String>& headers) {
                std::string headerString = "HTTP/1.1 " + std::to_string(statusCode) + " " + GetHttpStatusMessage(statusCode) + "\r\n";
                headerString += "Content-Type: " + std::string(contentType.GetRawString() ? contentType.GetRawString() : "") + "\r\n";
                if (bChunked) headerString += "Transfer-Encoding: chunked\r\n";
                headerString += "Connection: keep-alive\r\nServer: DotNetDupeWebApplication/1.0\r\n";
                auto keys = headers.GetKeys(); auto values = headers.GetValues();
                for (int i = 0; i < keys.GetLength(); ++i) {
                    headerString += std::string(keys[i].GetRawString() ? keys[i].GetRawString() : "") + ": " + std::string(values[i].GetRawString() ? values[i].GetRawString() : "") + "\r\n";
                }
                return headerString + "\r\n";
            }

            void HttpResponse::FlushHeaders() {
                if (m_bHeadersSent) return;
                m_bHeadersSent = true;
                WriteRaw(m_pStream, BuildResponseHeaderString(m_nStatusCode, m_sContentType, m_bChunked, m_headers));
            }

            void HttpResponse::WriteChunk(const System::String& data) {
                std::string rawData = std::string(data.GetRawString() ? data.GetRawString() : "");
                if (rawData.empty()) return;
                if (!m_bHeadersSent) {
                    m_bChunked = true;
                    FlushHeaders();
                }

                char hexBuf[32] = { 0 };
                snprintf(hexBuf, sizeof(hexBuf), "%zX\r\n", rawData.length());
                std::string chunk = std::string(hexBuf) + rawData + "\r\n";
                WriteRaw(m_pStream, chunk);
            }

            void HttpResponse::Flush() {
                if (!m_bHeadersSent) {
                    FlushHeaders();
                }
                if (m_bChunked) {
                    WriteRaw(m_pStream, "0\r\n\r\n");
                } else {
                    std::string body = std::string(m_sBody.GetRawString() ? m_sBody.GetRawString() : "");
                    if (!body.empty()) {
                        WriteRaw(m_pStream, body);
                    }
                }
            }

        }
    }
}

Generated by OpenCppCoverage (Version: 0.9.9.0)