/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
#include <algorithm>
#include <sstream>

#include "cripts/Lulu.hpp"
#include "cripts/Preamble.hpp"

namespace cripts
{

std::vector<cripts::string_view>
Url::Component::Split(const char delim)
{
  return cripts::Splitter(GetSV(), delim);
}

cripts::string_view
Url::Scheme::GetSV()
{
  if (_owner && _data.empty()) {
    const char *value = nullptr;
    int         len   = 0;

    _ensure_initialized(_owner);
    value = TSUrlSchemeGet(_owner->_bufp, _owner->_urlp, &len);
    _data = cripts::string_view(value, len);
  }

  return _data;
}

Url::Scheme
Url::Scheme::operator=(cripts::string_view scheme)
{
  CAssert(!_owner->ReadOnly()); // This can not be a read-only URL
  _ensure_initialized(_owner);
  TSUrlSchemeSet(_owner->_bufp, _owner->_urlp, scheme.data(), scheme.size());
  _owner->_modified = true;
  Reset();
  _loaded = false;

  return *this;
}

cripts::string_view
Url::Host::GetSV()
{
  if (_owner && _data.empty()) {
    const char *value = nullptr;
    int         len   = 0;

    _ensure_initialized(_owner);
    value   = TSUrlHostGet(_owner->_bufp, _owner->_urlp, &len);
    _data   = cripts::string_view(value, len);
    _loaded = true;
  }

  return _data;
}

Url::Host
Url::Host::operator=(cripts::string_view host)
{
  _ensure_initialized(_owner);
  CAssert(!_owner->ReadOnly()); // This can not be a read-only URL
  TSUrlHostSet(_owner->_bufp, _owner->_urlp, host.data(), host.size());
  _owner->_modified = true;
  Reset();
  _loaded = false;

  return *this;
}

Url::Port::operator integer() // This should not be explicit
{
  _ensure_initialized(_owner);
  if (_owner && _port < 0) {
    _port = TSUrlPortGet(_owner->_bufp, _owner->_urlp);
  }

  return _port;
}

Url::Port
Url::Port::operator=(int port)
{
  _ensure_initialized(_owner);
  CAssert(!_owner->ReadOnly()); // This can not be a read-only URL
  TSUrlPortSet(_owner->_bufp, _owner->_urlp, port);
  _owner->_modified = true;
  Reset();

  return *this;
}

cripts::string_view
Url::Path::GetSV()
{
  if (_segments.size() > 0) {
    std::ostringstream path;

    std::ranges::copy(_segments, std::ostream_iterator<cripts::string_view>(path, "/"));
    _storage.reserve(_size);
    _storage = std::string_view(path.str());
    if (_storage.size() > 0) {
      _storage.pop_back(); // Removes the trailing /
    }

    return {_storage};
  } else if (_owner && _data.empty()) {
    const char *value = nullptr;
    int         len   = 0;

    _ensure_initialized(_owner);
    value   = TSUrlPathGet(_owner->_bufp, _owner->_urlp, &len);
    _data   = cripts::string_view(value, len);
    _size   = len;
    _loaded = true;
  }

  return _data;
}

Url::Path::String
Url::Path::operator[](Segments::size_type ix)
{
  Url::Path::String ret;

  _ensure_initialized(_owner);
  _parser(); // Make sure the segments are loaded
  if (ix < _segments.size()) {
    ret._initialize(_segments[ix], this, ix);
  }

  return ret; // RVO
}

Url::Path
Url::Path::operator=(cripts::string_view path)
{
  _ensure_initialized(_owner);
  CAssert(!_owner->ReadOnly()); // This can not be a read-only URL
  TSUrlPathSet(_owner->_bufp, _owner->_urlp, path.data(), path.size());
  _owner->_modified = true;
  Reset();
  _loaded = false;

  return *this;
}

cripts::string
Url::Path::operator+=(cripts::string_view add)
{
  cripts::string str;

  if (add.size() > 0) {
    str.assign(GetSV());
    str += add;
    operator=(str);
  }

  return str; // RVO
}

Url::Path::String &
Url::Path::String::operator=(const cripts::string_view str)
{
  _ensure_initialized(_owner->_owner);
  CAssert(!_owner->_owner->ReadOnly()); // This can not be a read-only URL
  _owner->_size          -= _owner->_segments[_ix].size();
  _owner->_segments[_ix]  = str;
  _owner->_size          += str.size();
  _owner->_modified       = true;

  return *this;
}

void
Url::Path::Reset()
{
  Component::Reset();

  _segments.clear();
  _storage.clear();
  _size     = 0;
  _modified = false;
}

void
Url::Path::Push(cripts::string_view val)
{
  _parser();
  _modified = true;
  _segments.push_back(val);
}

void
Url::Path::Insert(Segments::size_type ix, cripts::string_view val)
{
  _parser();
  _modified = true;
  _segments.insert(_segments.begin() + ix, val);
}

void
Url::Path::_parser()
{
  if (_segments.size() == 0) {
    _segments = Split('/');
  }
}

Url::Query::Parameter &
Url::Query::Parameter::operator=(const cripts::string_view str)
{
  CAssert(!_owner->_standalone);
  _ensure_initialized(_owner->_owner);
  CAssert(!_owner->_owner->ReadOnly()); // This can not be a read-only URL
  auto iter = _owner->_hashed.find(_name);

  if (iter != _owner->_hashed.end()) {
    iter->second = str; // Can be an empty string here!
  } else {
    _owner->_ordered.push_back(_name);
    _owner->_hashed[_name] = str;
  }
  _owner->_modified = true;

  return *this;
}

cripts::string_view
Url::Query::GetSV()
{
  if (!_standalone) {
    _ensure_initialized(_owner);
  }
  if (_ordered.size() > 0) {
    _storage.clear();
    _storage.reserve(_size);

    // ToDo: This is wonky, has to be a better std:: iteration to do here
    for (const auto key : _ordered) {
      auto iter = _hashed.find(key);

      if (_storage.size() > 0) {
        _storage += "&";
      }

      if (iter != _hashed.end()) {
        _storage += iter->first;
        if (iter->second.size() > 0) {
          _storage += '=';
          _storage += iter->second;
        }
      }
    }

    return {_storage};
  }

  // This gets weird when we modify the query parameter components, and can possibly empty
  // the entire query parameter. At which point, we don't want to reload the string_view
  // from the URL object inside of ATS...
  if (_owner && !_loaded) {
    const char *value = nullptr;
    int         len   = 0;

    value   = TSUrlHttpQueryGet(_owner->_bufp, _owner->_urlp, &len);
    _data   = cripts::string_view(value, len);
    _size   = len;
    _loaded = true;
  }

  return _data;
}

Url::Query
Url::Query::operator=(cripts::string_view query)
{
  CAssert(!_standalone);
  _ensure_initialized(_owner);
  CAssert(!_owner->ReadOnly()); // This can not be a read-only URL
  TSUrlHttpQuerySet(_owner->_bufp, _owner->_urlp, query.data(), query.size());
  _owner->_modified = true;
  Reset();
  _loaded = false;

  return *this;
}

cripts::string
Url::Query::operator+=(cripts::string_view add)
{
  cripts::string str;

  if (add.size() > 0) {
    str.assign(GetSV());
    str += add;
    operator=(str);
  }

  return str; // RVO
}

Url::Query::Parameter
Url::Query::operator[](cripts::string_view param)
{
  // Make sure the hash and vector are populated, but only if we have an owner
  if (!_standalone) {
    _ensure_initialized(_owner);
  }
  _parser();

  Parameter ret;
  auto      iter = _hashed.find(param);

  if (iter != _hashed.end()) {
    ret._initialize(iter->first, iter->second, this);
  } else {
    ret._initialize(param, "", this);
  }

  return ret;
}

void
Url::Query::Erase(cripts::string_view param)
{
  // Make sure the hash and vector are populated
  _parser();

  auto iter  = _hashed.find(param);
  auto viter = std::ranges::find(_ordered, param);

  if (iter != _hashed.end()) {
    _size -= iter->second.size(); // Size of the erased value
    _hashed.erase(iter);

    CAssert(viter != _ordered.end());
    _size -= viter->size(); // Length of the erased key
    _ordered.erase(viter);

    if (_ordered.size() == 0) {
      Reset();
    }
    _modified = true; // Make sure to set this after we reset above ...
  }
}

void
Url::Query::Erase(std::initializer_list<cripts::string_view> list, bool keep)
{
  if (keep) {
    // Make sure the hash and vector are populated
    _parser();

    for (auto viter = _ordered.begin(); viter != _ordered.end();) {
      if (list.end() == std::ranges::find(list, *viter)) {
        auto iter = _hashed.find(*viter);

        CAssert(iter != _hashed.end());
        _size -= iter->second.size(); // Size of the erased value
        _size -= viter->size();       // Length of the erased key
        _hashed.erase(iter);
        viter     = _ordered.erase(viter);
        _modified = true;
      } else {
        ++viter;
      }
    }
    if (_ordered.size() == 0) {
      Reset();
    }
  } else {
    for (auto &it : list) {
      Erase(it);
    }
  }
}

void
Url::Query::Reset()
{
  Component::Reset();

  _ordered.clear();
  _hashed.clear();
  _storage.clear();
  _size     = 0;
  _modified = false;
}

void
Url::Query::_parser()
{
  if (_ordered.size() == 0) {
    for (const auto sv : Split('&')) {
      const auto          eq  = sv.find_first_of('=');
      cripts::string_view key = sv.substr(0, eq);
      cripts::string_view val;

      if (eq != cripts::string_view::npos) {
        val = sv.substr(eq + 1);
      }

      _ordered.push_back(key); // Keep the order
      _hashed[key] = val;
    }
  }
}

cripts::string
Url::String()
{
  cripts::string ret;

  CAssert(_context);
  _ensure_initialized(this);
  int   full_len = 0;
  char *full_str = TSUrlStringGet(_bufp, _urlp, &full_len);

  if (full_str) {
    ret.assign(full_str, full_len);
    TSfree(static_cast<void *>(full_str));
  }

  return ret;
}

Pristine::URL &
Pristine::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_urls.pristine);
  return context->_urls.pristine;
}

void
Pristine::URL::_initialize()
{
  Pristine::URL *url = &_context->_urls.pristine;

  TSAssert(_context->state.txnp);
  if (TSHttpTxnPristineUrlGet(_context->state.txnp, &url->_bufp, &url->_urlp) != TS_SUCCESS) {
    _context->state.error.Fail();
  } else {
    super_type::_initialize(); // Only if successful
  }
}

void
Client::URL::_initialize()
{
  if (_context->rriValid()) {
    super_type::_initialize();
    _bufp    = _context->rri->requestBufp;
    _hdr_loc = _context->rri->requestHdrp;
    _urlp    = _context->rri->requestUrl;
  } else {
    Client::Request &req = Client::Request::_get(_context); // Repurpose / create the shared request object

    _bufp    = req.BufP();
    _hdr_loc = req.MLoc();

    if (TSHttpHdrUrlGet(_bufp, _hdr_loc, &_urlp) != TS_SUCCESS) {
      _context->state.error.Fail();
    } else {
      super_type::_initialize();
    }
  }
}

Client::URL &
Client::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_urls.request);
  return context->_urls.request;
}

bool
Client::URL::_update()
{
  _ensure_initialized(this);
  path.Flush();
  query.Flush();

  return _modified;
}

void
Remap::From::URL::_initialize()
{
  if (_context->rriValid()) {
    super_type::_initialize();
    _bufp    = _context->rri->requestBufp;
    _hdr_loc = _context->rri->requestHdrp;
    _urlp    = _context->rri->mapFromUrl;
  } else {
    _context->state.error.Fail();
  }
}

Remap::From::URL &
Remap::From::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_urls.remap.from);
  return context->_urls.remap.from;
}

void
Remap::To::URL::_initialize()
{
  if (_context->rriValid()) {
    super_type::_initialize();
    _bufp    = _context->rri->requestBufp;
    _hdr_loc = _context->rri->requestHdrp;
    _urlp    = _context->rri->mapToUrl;
  } else {
    _context->state.error.Fail();
  }
}

Remap::To::URL &
Remap::To::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_urls.remap.to);
  return context->_urls.remap.to;
}

Cache::URL &
Cache::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_cache.url);
  return context->_cache.url;
}

void
Cache::URL::_initialize()
{
  Cache::URL      *url = &_context->_cache.url;
  Client::Request &req = Client::Request::_get(_context); // Repurpose / create the shared request object

  switch (_context->state.hook) {
  // In these hooks, the internal cache-url has been properly set
  case TS_HTTP_SEND_RESPONSE_HDR_HOOK:
  case TS_HTTP_READ_RESPONSE_HDR_HOOK:
  case TS_HTTP_SEND_REQUEST_HDR_HOOK:
  case TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK:
  case TS_HTTP_TXN_CLOSE_HOOK:
    if (TSUrlCreate(req.BufP(), &url->_urlp) == TS_SUCCESS) {
      TSAssert(_context->state.txnp);
      if (TSHttpTxnCacheLookupUrlGet(_context->state.txnp, req.BufP(), url->_urlp) != TS_SUCCESS) {
        _context->state.error.Fail();
        return;
      }
    } else {
      _context->state.error.Fail();
      return;
    }
    break;
  default: { // This means we have to clone. ToDo: For now, this is implicitly using Client::URL
    Client::URL &src = Client::URL::_get(_context);

    if (TSUrlClone(req.BufP(), req.BufP(), src.UrlP(), &url->_urlp) != TS_SUCCESS) {
      _context->state.error.Fail();
      return;
    }
  } break;
  }

  // Only if we succeeded above
  super_type::_initialize();
  _bufp    = req.BufP();
  _hdr_loc = req.MLoc();
}

// This has to be implemented here, since the cripts::Context is not complete yet
bool
Cache::URL::_update()
{
  // For correctness, we will also make sure the Path and Query objects are flushed
  path.Flush();
  query.Flush();

  if (_modified) {
    _ensure_initialized(&_context->_cache.url);
    TSAssert(_context->state.txnp);
    _modified = false;
    if (TS_SUCCESS == TSHttpTxnCacheLookupUrlSet(_context->state.txnp, _bufp, _urlp)) {
      if (_context->p_instance.DebugOn()) {
        _context->p_instance.debug("Successfully setting cache-key to {}", String());
      }
      return true;
    } else {
      if (_context->p_instance.DebugOn()) {
        _context->p_instance.debug("Could not set the cache key to {}", String());
      }
      _context->state.error.Fail();
      return false;
    }
  }

  return false;
}

// ToDo: This may need more work, to understand which hooks the parent URL is actually available
Parent::URL &
Parent::URL::_get(cripts::Context *context)
{
  _ensure_initialized(&context->_urls.parent);
  return context->_urls.parent;
}

void
Parent::URL::_initialize()
{
  Parent::URL     *url = &_context->_urls.parent;
  Client::Request &req = Client::Request::_get(_context); // Repurpose / create the shared request object

  if (TSUrlCreate(req.BufP(), &url->_urlp) == TS_SUCCESS) {
    TSAssert(_context->state.txnp);
    if (TSHttpTxnParentSelectionUrlGet(_context->state.txnp, req.BufP(), url->_urlp) != TS_SUCCESS) {
      _context->state.error.Fail();
      return;
    }
  } else {
    _context->state.error.Fail();
    return;
  }

  // Only if successful above
  super_type::_initialize();
  _bufp    = req.BufP();
  _hdr_loc = req.MLoc();
}

} // namespace cripts
