/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (c) 2013-2014,  Regents of the University of California.
 * All rights reserved.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * This file licensed under New BSD License.  See COPYING for detailed information about
 * ndn-cxx library copyright, permissions, and redistribution restrictions.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 */

#include "regex-top-matcher.hpp"

#include "regex-backref-manager.hpp"
#include "regex-pattern-list-matcher.hpp"

namespace ndn {

RegexTopMatcher::RegexTopMatcher(const std::string& expr, const std::string& expand)
  : RegexMatcher(expr, EXPR_TOP),
    m_expand(expand),
    m_secondaryUsed(false)
{
  m_primaryBackRefManager = make_shared<RegexBackrefManager>();
  m_secondaryBackRefManager = make_shared<RegexBackrefManager>();
  compile();
}

RegexTopMatcher::~RegexTopMatcher()
{
  // delete m_backRefManager;
}

void
RegexTopMatcher::compile()
{
  std::string errMsg = "Error: RegexTopMatcher.Compile(): ";

  std::string expr = m_expr;

  if ('$' != expr[expr.size() - 1])
    expr = expr + "<.*>*";
  else
    expr = expr.substr(0, expr.size()-1);

  if ('^' != expr[0])
    m_secondaryMatcher = make_shared<RegexPatternListMatcher>("<.*>*" + expr,
                                                              cref(m_secondaryBackRefManager));
  else
    expr = expr.substr(1, expr.size()-1);

  m_primaryMatcher = make_shared<RegexPatternListMatcher>(func_lib::cref(expr),
                                                          func_lib::cref(m_primaryBackRefManager));
}

bool
RegexTopMatcher::match(const Name& name)
{
  m_secondaryUsed = false;

  m_matchResult.clear();

  if (m_primaryMatcher->match(name, 0, name.size()))
    {
      m_matchResult = m_primaryMatcher->getMatchResult();
      return true;
    }
  else
    {
      if (NULL != m_secondaryMatcher && m_secondaryMatcher->match(name, 0, name.size()))
        {
          m_matchResult = m_secondaryMatcher->getMatchResult();
          m_secondaryUsed = true;
          return true;
        }
      return false;
    }
}

bool
RegexTopMatcher::match (const Name& name, const int& offset, const int& len)
{
  return match(name);
}

Name
RegexTopMatcher::expand (const std::string& expandStr)
{
  Name result;

  shared_ptr<RegexBackrefManager> backRefManager =
    (m_secondaryUsed ? m_secondaryBackRefManager : m_primaryBackRefManager);

  int backRefNum = backRefManager->size();

  std::string expand;

  if (expandStr != "")
    expand = expandStr;
  else
    expand = m_expand;

  size_t offset = 0;
  while (offset < expand.size())
    {
      std::string item = getItemFromExpand(expand, offset);
      if (item[0] == '<')
        {
          result.append(item.substr(1, item.size() - 2));
        }
      if (item[0] == '\\')
        {

          int index = atoi(item.substr(1, item.size() - 1).c_str());

          if (0 == index){
            std::vector<name::Component>::iterator it = m_matchResult.begin();
            std::vector<name::Component>::iterator end = m_matchResult.end();
            for(; it != end; it++)
              result.append (*it);
          }
          else if (index <= backRefNum)
            {
              std::vector<name::Component>::const_iterator it =
                backRefManager->getBackRef (index - 1)->getMatchResult ().begin();
              std::vector<name::Component>::const_iterator end =
                backRefManager->getBackRef (index - 1)->getMatchResult ().end();
              for(; it != end; it++)
                result.append (*it);
            }
          else
            throw RegexMatcher::Error("Exceed the range of back reference!");
        }
    }
  return result;
}

std::string
RegexTopMatcher::getItemFromExpand(const std::string& expand, size_t& offset)
{
  size_t begin = offset;

  if (expand[offset] == '\\')
    {
      offset++;
      if (offset >= expand.size())
        throw RegexMatcher::Error("wrong format of expand string!");

      while(expand[offset] <= '9' and expand[offset] >= '0'){
        offset++;
        if (offset > expand.size())
          throw RegexMatcher::Error("wrong format of expand string!");
      }
      if (offset > begin + 1)
        return expand.substr(begin, offset - begin);
      else
        throw RegexMatcher::Error("wrong format of expand string!");
    }
  else if (expand[offset] == '<')
    {
      offset++;
      if (offset >= expand.size())
        throw RegexMatcher::Error("wrong format of expand string!");

      size_t left = 1;
      size_t right = 0;
      while(right < left)
        {
          if (expand[offset] == '<')
            left++;
          if (expand[offset] == '>')
            right++;
          offset++;
          if (offset >= expand.size())
            throw RegexMatcher::Error("wrong format of expand string!");
        }
      return expand.substr(begin, offset - begin);
    }
  else
    throw RegexMatcher::Error("wrong format of expand string!");
}

shared_ptr<RegexTopMatcher>
RegexTopMatcher::fromName(const Name& name, bool hasAnchor)
{
  Name::const_iterator it = name.begin();
  std::string regexStr("^");

  for(; it != name.end(); it++)
    {
      regexStr.append("<");
      regexStr.append(convertSpecialChar(it->toEscapedString()));
      regexStr.append(">");
    }

  if (hasAnchor)
    regexStr.append("$");

  // OSX 10.9 has problems with just cref
  return make_shared<RegexTopMatcher>(func_lib::cref(regexStr));
}

std::string
RegexTopMatcher::convertSpecialChar(const std::string& str)
{
  std::string newStr;
  for(size_t i = 0; i < str.size(); i++)
    {
      char c = str[i];
      switch (c)
        {
        case '.':
        case '[':
        case '{':
        case '}':
        case '(':
        case ')':
        case '\\':
        case '*':
        case '+':
        case '?':
        case '|':
        case '^':
        case '$':
          newStr.push_back('\\');
        default:
          newStr.push_back(c);
        }
    }

  return newStr;
}

}//ndn
