/*
 * Header.cpp
 *
 * Copyright (C) 2022 by Posit Software, PBC
 *
 * Unless you have received this program directly from Posit Software pursuant
 * to the terms of a commercial license agreement with Posit Software, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/http/Header.hpp>

#include <iostream>
#include <algorithm>

#include <boost/algorithm/string.hpp>

namespace rstudio {
namespace core {
namespace http {
   
bool HeaderNamePredicate::operator()(const Header& header) const
{ 
   return boost::iequals(name_, header.name);
}
   
bool containsHeader(const Headers& headers, const std::string& name)
{
   return findHeader(headers, name) != headers.end();
}

Headers::const_iterator findHeader(const Headers& headers, 
                                   const std::string& name)
{
   return std::find_if(headers.begin(), 
                       headers.end(), 
                       HeaderNamePredicate(name));
}

std::string headerValue(const Headers& headers, const std::string& name)
{
   Headers::const_iterator it = std::find_if(headers.begin(), 
                                             headers.end(), 
                                             HeaderNamePredicate(name));

   if ( it != headers.end() )
      return (*it).value;
   else
      return std::string();
}

std::vector<std::string> headerValues(const Headers& headers, const std::string& name)
{
   std::vector<std::string> values;

   Headers::const_iterator it = headers.begin();
   for (;;)
   {
      it = std::find_if(it, 
                        headers.end(), 
                        HeaderNamePredicate(name));
      if (it == headers.end())
         break;

      values.push_back((*it).value);
      it++;
   }
   return values;
}

bool parseHeader(const std::string& line, Header* pHeader)
{
   // parse the name and value out of the header
   std::string::size_type pos = line.find(": ");
   if ( pos != std::string::npos )
   {
      pHeader->name = line.substr(0, pos);
      pHeader->value = line.substr(pos + 2);
      boost::algorithm::trim(pHeader->name);
      boost::algorithm::trim(pHeader->value);
      return true;
   }
   else
   {
      return false;
   }
}
   
void parseHeaders(std::istream& is, Headers* pHeaders)
{
   bool parsing = false;
   std::string line;
   while (std::getline(is, line))
   {
      // this is either leading whitespace or a termination condition
      if (line == "\r")
      {
         if (parsing)
            break;
         else
            continue;
      }
      
      Header header;
      if (parseHeader(line, &header))
         pHeaders->push_back(header);
      parsing = true;
   }
}   
   
} // namespace http
} // namespace core
} // namespace rstudio
