/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2015 Kitware, Inc., Gregor Jasny

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "RegexExplorer.h"

RegexExplorer::RegexExplorer(QWidget* p) : QDialog(p), m_matched(false)
{
  this->setupUi(this);

  for(int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i)
    {
    matchNumber->addItem(
      QString("Match %1").arg(QString::number(i)),
      QVariant(i));
    }
  matchNumber->setCurrentIndex(0);
}

void RegexExplorer::setStatusColor(QWidget* widget, bool successful)
{
  QColor color = successful ? QColor(0, 127, 0) : Qt::red;

  QPalette palette = widget->palette();
  palette.setColor(QPalette::Foreground, color);
  widget->setPalette(palette);
}

void RegexExplorer::on_regularExpression_textChanged(const QString& text)
{
#ifdef QT_NO_STL
  m_regex = text.toAscii().constData();
#else
  m_regex = text.toStdString();
#endif

  bool validExpression =
    stripEscapes(m_regex) && m_regexParser.compile(m_regex);
  if(!validExpression)
    {
    m_regexParser.set_invalid();
    }

  setStatusColor(labelRegexValid, validExpression);

  on_inputText_textChanged();
}

void RegexExplorer::on_inputText_textChanged()
{
  if(m_regexParser.is_valid())
    {
    QString plainText = inputText->toPlainText();
#ifdef QT_NO_STL
    m_text = plainText.toAscii().constData();
#else
    m_text = plainText.toStdString();
#endif
    m_matched = m_regexParser.find(m_text);
    }
  else
    {
    m_matched = false;
    }

  setStatusColor(labelRegexMatch, m_matched);

  if(!m_matched)
    {
    clearMatch();
    return;
    }

#ifdef QT_NO_STL
  QString matchText = m_regexParser.match(0).c_str();
#else
  QString matchText = QString::fromStdString(m_regexParser.match(0));
#endif
  match0->setPlainText(matchText);

  on_matchNumber_currentIndexChanged(matchNumber->currentIndex());
}

void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
{
  if(!m_matched)
    {
    return;
    }

  QVariant itemData = matchNumber->itemData(index);
  int idx = itemData.toInt();

  if(idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP)
    {
    return;
    }

#ifdef QT_NO_STL
  QString match = m_regexParser.match(idx).c_str();
#else
  QString match = QString::fromStdString(m_regexParser.match(idx));
#endif
  matchN->setPlainText(match);
}

void RegexExplorer::clearMatch()
{
  match0->clear();
  matchN->clear();
}

bool RegexExplorer::stripEscapes(std::string& source)
{
  const char* in = source.c_str();

  std::string result;
  result.reserve(source.size());

  for(char inc = *in; inc != '\0'; inc = *++in)
    {
    if(inc == '\\')
      {
      char nextc = in[1];
      if(nextc == 't')
        {
        result.append(1, '\t');
        in++;
        }
      else if(nextc == 'n')
        {
        result.append(1, '\n');
        in++;
        }
      else if(nextc == 't')
        {
        result.append(1, '\t');
        in++;
        }
      else if(isalnum(nextc) || nextc == '\0')
        {
        return false;
        }
      else
        {
        result.append(1, nextc);
        in++;
        }
      }
    else
      {
        result.append(1, inc);
      }
    }

    source = result;
    return true;
}