SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
    QWidget(parent)

/**************************************************************************
**
** Author: Orgad Shaneh <example@nnthink.com>
** Contact: http://example.com
**
** This file is part of Qt Creator.
**
**
****************************************************************************/

#include "clearcaseconstants.h"
#include "clearcasesettings.h"
#include "clearcaseplugin.h"
#include "settingspage.h"

#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>

#include <QCoreApplication>
#include <QFileDialog>
#include <QTextStream>

using namespace ClearCase::Internal;
using namespace Utils;

{
    m_ui.setupUi(this);
    m_ui.commandPathChooser->setPromptDialogTitle(tr("ClearCase Command"));
    m_ui.commandPathChooser->setExpectedKind(PathChooser::ExistingCommand);
}

ClearCaseSettings SettingsPageWidget::settings() const
{
    ClearCaseSettings rc;
    rc.ccCommand = m_ui.commandPathChooser->rawPath();
    rc.ccBinaryPath = m_ui.commandPathChooser->path();
    rc.timeOutS = m_ui.timeOutSpinBox->value();
    rc.autoCheckOut = m_ui.autoCheckOutCheckBox->isChecked();
    if (m_ui.graphicalDiffRadioButton->isChecked())
        rc.diffType = GraphicalDiff;
    else if (m_ui.externalDiffRadioButton->isChecked())
        rc.diffType = ExternalDiff;
    rc.autoAssignActivityName = m_ui.autoAssignActivityCheckBox->isChecked();
    rc.historyCount = m_ui.historyCountSpinBox->value();
    rc.promptToCheckIn = m_ui.promptCheckBox->isChecked();
    rc.disableIndexer = m_ui.disableIndexerCheckBox->isChecked();
    rc.diffArgs = m_ui.diffArgsEdit->text();
    rc.indexOnlyVOBs = m_ui.indexOnlyVOBsEdit->text();
    rc.extDiffAvailable = m_ui.externalDiffRadioButton->isEnabled();
    return rc;
}

void SettingsPageWidget::setSettings(const ClearCaseSettings &s)
{
    m_ui.commandPathChooser->setPath(s.ccCommand);
    m_ui.timeOutSpinBox->setValue(s.timeOutS);
    m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
    bool extDiffAvailable = !Utils::Environment::systemEnvironment().searchInPath(QLatin1String("diff")).isEmpty();
    if (extDiffAvailable) {
        m_ui.diffWarningLabel->setVisible(false);
    } else {
        QString diffWarning = tr("In order to use External diff, 'diff' command needs to be accessible.");
        if (HostOsInfo::isWindowsHost()) {
            diffWarning.append(tr(" DiffUtils is available for free download "
                                  "here. "
                                  "Please extract it to a directory in your PATH."));
        }
        m_ui.diffWarningLabel->setText(diffWarning);
        m_ui.externalDiffRadioButton->setEnabled(false);
    }
    if (extDiffAvailable && s.diffType == ExternalDiff)
        m_ui.externalDiffRadioButton->setChecked(true);
    else
        m_ui.graphicalDiffRadioButton->setChecked(true);
    m_ui.autoAssignActivityCheckBox->setChecked(s.autoAssignActivityName);
    m_ui.historyCountSpinBox->setValue(s.historyCount);
    m_ui.promptCheckBox->setChecked(s.promptToCheckIn);
    m_ui.disableIndexerCheckBox->setChecked(s.disableIndexer);
    m_ui.diffArgsEdit->setText(s.diffArgs);
    m_ui.indexOnlyVOBsEdit->setText(s.indexOnlyVOBs);
}

QString SettingsPageWidget::searchKeywords() const
{
    QString rc;
    QLatin1Char sep(' ');
    QTextStream(&rc) << m_ui.commandLabel->text()
            << sep << m_ui.autoCheckOutCheckBox->text()
            << sep << m_ui.externalDiffRadioButton->text()
            << sep << m_ui.graphicalDiffRadioButton->text()
            << sep << m_ui.diffArgsLabel->text()
            << sep << m_ui.historyCountLabel->text()
            << sep << m_ui.promptCheckBox->text()
            << sep << m_ui.disableIndexerCheckBox->text()
            << sep << m_ui.timeOutLabel->text()
            << sep << m_ui.indexOnlyVOBsLabel->text()
               ;
    rc.remove(QLatin1Char('&'));
    return rc;
}

SettingsPage::SettingsPage() :
    m_widget(0)
{
    setId(QLatin1String(ClearCase::Constants::VCS_ID_CLEARCASE));
    setDisplayName(tr("ClearCase"));
}

QWidget *SettingsPage::createPage(QWidget *parent)
{
    m_widget = new SettingsPageWidget(parent);
    m_widget->setSettings(ClearCasePlugin::instance()->settings());
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
    return m_widget;
}

void SettingsPage::apply()
{
    ClearCasePlugin::instance()->setSettings(m_widget->settings());
}

bool SettingsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}


{
    ClearCasePlugin::instance()->setSettings(m_widget->settings());
}

/**************************************************************************
**
** Author: Orgad Shaneh <example@nnthink.com>
** Contact: http://example.com
**
** This file is part of Qt Creator.
**
**
****************************************************************************/

#include "clearcaseconstants.h"
#include "clearcasesettings.h"
#include "clearcaseplugin.h"
#include "settingspage.h"

#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>

#include <QCoreApplication>
#include <QFileDialog>
#include <QTextStream>

using namespace ClearCase::Internal;
using namespace Utils;

SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
    QWidget(parent)
{
    m_ui.setupUi(this);
    m_ui.commandPathChooser->setPromptDialogTitle(tr("ClearCase Command"));
    m_ui.commandPathChooser->setExpectedKind(PathChooser::ExistingCommand);
}

ClearCaseSettings SettingsPageWidget::settings() const
{
    ClearCaseSettings rc;
    rc.ccCommand = m_ui.commandPathChooser->rawPath();
    rc.ccBinaryPath = m_ui.commandPathChooser->path();
    rc.timeOutS = m_ui.timeOutSpinBox->value();
    rc.autoCheckOut = m_ui.autoCheckOutCheckBox->isChecked();
    if (m_ui.graphicalDiffRadioButton->isChecked())
        rc.diffType = GraphicalDiff;
    else if (m_ui.externalDiffRadioButton->isChecked())
        rc.diffType = ExternalDiff;
    rc.autoAssignActivityName = m_ui.autoAssignActivityCheckBox->isChecked();
    rc.historyCount = m_ui.historyCountSpinBox->value();
    rc.promptToCheckIn = m_ui.promptCheckBox->isChecked();
    rc.disableIndexer = m_ui.disableIndexerCheckBox->isChecked();
    rc.diffArgs = m_ui.diffArgsEdit->text();
    rc.indexOnlyVOBs = m_ui.indexOnlyVOBsEdit->text();
    rc.extDiffAvailable = m_ui.externalDiffRadioButton->isEnabled();
    return rc;
}

void SettingsPageWidget::setSettings(const ClearCaseSettings &s)
{
    m_ui.commandPathChooser->setPath(s.ccCommand);
    m_ui.timeOutSpinBox->setValue(s.timeOutS);
    m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
    bool extDiffAvailable = !Utils::Environment::systemEnvironment().searchInPath(QLatin1String("diff")).isEmpty();
    if (extDiffAvailable) {
        m_ui.diffWarningLabel->setVisible(false);
    } else {
        QString diffWarning = tr("In order to use External diff, 'diff' command needs to be accessible.");
        if (HostOsInfo::isWindowsHost()) {
            diffWarning.append(tr(" DiffUtils is available for free download "
                                  "here. "
                                  "Please extract it to a directory in your PATH."));
        }
        m_ui.diffWarningLabel->setText(diffWarning);
        m_ui.externalDiffRadioButton->setEnabled(false);
    }
    if (extDiffAvailable && s.diffType == ExternalDiff)
        m_ui.externalDiffRadioButton->setChecked(true);
    else
        m_ui.graphicalDiffRadioButton->setChecked(true);
    m_ui.autoAssignActivityCheckBox->setChecked(s.autoAssignActivityName);
    m_ui.historyCountSpinBox->setValue(s.historyCount);
    m_ui.promptCheckBox->setChecked(s.promptToCheckIn);
    m_ui.disableIndexerCheckBox->setChecked(s.disableIndexer);
    m_ui.diffArgsEdit->setText(s.diffArgs);
    m_ui.indexOnlyVOBsEdit->setText(s.indexOnlyVOBs);
}

QString SettingsPageWidget::searchKeywords() const
{
    QString rc;
    QLatin1Char sep(' ');
    QTextStream(&rc) << m_ui.commandLabel->text()
            << sep << m_ui.autoCheckOutCheckBox->text()
            << sep << m_ui.externalDiffRadioButton->text()
            << sep << m_ui.graphicalDiffRadioButton->text()
            << sep << m_ui.diffArgsLabel->text()
            << sep << m_ui.historyCountLabel->text()
            << sep << m_ui.promptCheckBox->text()
            << sep << m_ui.disableIndexerCheckBox->text()
            << sep << m_ui.timeOutLabel->text()
            << sep << m_ui.indexOnlyVOBsLabel->text()
               ;
    rc.remove(QLatin1Char('&'));
    return rc;
}

SettingsPage::SettingsPage() :
    m_widget(0)
{
    setId(QLatin1String(ClearCase::Constants::VCS_ID_CLEARCASE));
    setDisplayName(tr("ClearCase"));
}

QWidget *SettingsPage::createPage(QWidget *parent)
{
    m_widget = new SettingsPageWidget(parent);
    m_widget->setSettings(ClearCasePlugin::instance()->settings());
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
    return m_widget;
}

void SettingsPage::apply()

bool SettingsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}


/**************************************************************************
**
** Author: Orgad Shaneh <example@nnthink.com>
** Contact: http://example.com
**
** This file is part of Qt Creator.
**
**
****************************************************************************/

#include "clearcaseconstants.h"
#include "clearcasesettings.h"
#include "clearcaseplugin.h"
#include "settingspage.h"

#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/environment.h>
#include <utils/hostosinfo.h>
#include <utils/pathchooser.h>

#include <QCoreApplication>
#include <QFileDialog>
#include <QTextStream>

using namespace ClearCase::Internal;
using namespace Utils;

SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
    QWidget(parent)
{
    m_ui.setupUi(this);
    m_ui.commandPathChooser->setPromptDialogTitle(tr("ClearCase Command"));
    m_ui.commandPathChooser->setExpectedKind(PathChooser::ExistingCommand);
}

ClearCaseSettings SettingsPageWidget::settings() const
{
    ClearCaseSettings rc;
    rc.ccCommand = m_ui.commandPathChooser->rawPath();
    rc.ccBinaryPath = m_ui.commandPathChooser->path();
    rc.timeOutS = m_ui.timeOutSpinBox->value();
    rc.autoCheckOut = m_ui.autoCheckOutCheckBox->isChecked();
    if (m_ui.graphicalDiffRadioButton->isChecked())
        rc.diffType = GraphicalDiff;
    else if (m_ui.externalDiffRadioButton->isChecked())
        rc.diffType = ExternalDiff;
    rc.autoAssignActivityName = m_ui.autoAssignActivityCheckBox->isChecked();
    rc.historyCount = m_ui.historyCountSpinBox->value();
    rc.promptToCheckIn = m_ui.promptCheckBox->isChecked();
    rc.disableIndexer = m_ui.disableIndexerCheckBox->isChecked();
    rc.diffArgs = m_ui.diffArgsEdit->text();
    rc.indexOnlyVOBs = m_ui.indexOnlyVOBsEdit->text();
    rc.extDiffAvailable = m_ui.externalDiffRadio

return rc;
}

void SettingsPageWidget::setSettings(const ClearCaseSettings &s)
{
    m_ui.commandPathChooser->setPath(s.ccCommand);
    m_ui.timeOutSpinBox->setValue(s.timeOutS);
    m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
    bool extDiffAvailable = !Utils::Environment::systemEnvironment().searchInPath(QLatin1String("diff")).isEmpty();
    if (extDiffAvailable) {
        m_ui.diffWarningLabel->setVisible(false);
    } else {
        QString diffWarning = tr("In order to use External diff, 'diff' command needs to be accessible.");
        if (HostOsInfo::isWindowsHost()) {
            diffWarning.append(tr(" DiffUtils is available for free download "
                                  "here. "
                                  "Please extract it to a directory in your PATH."));
        }
        m_ui.diffWarningLabel->setText(diffWarning);
        m_ui.externalDiffRadioButton->setEnabled(false);
    }
    if (extDiffAvailable && s.diffType == ExternalDiff)
        m_ui.externalDiffRadioButton->setChecked(true);
    else
        m_ui.graphicalDiffRadioButton->setChecked(true);
    m_ui.autoAssignActivityCheckBox->setChecked(s.autoAssignActivityName);
    m_ui.historyCountSpinBox->setValue(s.historyCount);
    m_ui.promptCheckBox->setChecked(s.promptToCheckIn);
    m_ui.disableIndexerCheckBox->setChecked(s.disableIndexer);
    m_ui.diffArgsEdit->setText(s.diffArgs);
    m_ui.indexOnlyVOBsEdit->setText(s.indexOnlyVOBs);
}

QString SettingsPageWidget::searchKeywords() const
{
    QString rc;
    QLatin1Char sep(' ');
    QTextStream(&rc) << m_ui.commandLabel->text()
            << sep << m_ui.autoCheckOutCheckBox->text()
            << sep << m_ui.externalDiffRadioButton->text()
            << sep << m_ui.graphicalDiffRadioButton->text()
            << sep << m_ui.diffArgsLabel->text()
            << sep << m_ui.historyCountLabel->text()
            << sep << m_ui.promptCheckBox->text()
            << sep << m_ui.disableIndexerCheckBox->text()
            << sep << m_ui.timeOutLabel->text()
            << sep << m_ui.indexOnlyVOBsLabel->text()
               ;
    rc.remove(QLatin1Char('&'));
    return rc;
}

SettingsPage::SettingsPage() :
    m_widget(0)
{
    setId(QLatin1String(ClearCase::Constants::VCS_ID_CLEARCASE));
    setDisplayName(tr("ClearCase"));
}

QWidget *SettingsPage::createPage(QWidget *parent)
{
    m_widget = new SettingsPageWidget(parent);
    m_widget->setSettings(ClearCasePlugin::instance()->settings());
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
    return m_widget;
}

void SettingsPage::apply()
{
    ClearCasePlugin::instance()->setSettings(m_widget->settings());
}

bool SettingsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}


exception::exception(const std::string &header_,
                       const std::string &filename_,
                       const std::string &function_,
                       const int line_,
                       const std::string &message_) :
    header(header_),
    filename(filename_),
    function(function_),
    message(message_),
    line(line_),
    exceptionMessage(toString())

#include <sstream>

#include <occa/utils/exception.hpp>
#include <occa/internal/utils/string.hpp>
#include <occa/internal/utils/sys.hpp>

namespace occa {

{}

  exception::~exception() throw() {}

  const char* exception::what() const throw() {
    return exceptionMessage.c_str();
  }

  std::string exception::toString(const int stackTraceStart) const {
    std::stringstream ss;

    // Pad message lines
    strVector lines = split(message, '\n');
    const int lineCount = (int) lines.size();

    for (int i = 0; i < lineCount; ++i) {
      if (i) {
        ss << "\n               ";
      }
      ss << lines[i];
    }
    const std::string prettyMessage = ss.str();
    ss.str("");

    std::string banner = "---[ " + header + " ]";
    ss << '\n'
       << banner << std::string(80 - banner.size(), '-') << '\n'
       << location()
       << "    Message  : " << prettyMessage << '\n'
       << "    Stack\n"
       << sys::stacktrace(stackTraceStart, "      ")
       << std::string(80, '=') << '\n';

    return ss.str();
  }

  std::string exception::location() const {
    std::stringstream ss;
    ss << "    File     : " << filename << '\n'
       << "    Line     : " << line     << '\n'
       << "    Function : " << function << '\n';
    return ss.str();
  }

  std::ostream& operator << (std::ostream& out,
                             const exception &exc) {
    out << exc.toString() << std::flush;
    return out;
  }
}


{
    out << exc.toString() << std::flush;
    return out;
  }

#include <sstream>

#include <occa/utils/exception.hpp>
#include <occa/internal/utils/string.hpp>
#include <occa/internal/utils/sys.hpp>

namespace occa {
  exception::exception(const std::string &header_,
                       const std::string &filename_,
                       const std::string &function_,
                       const int line_,
                       const std::string &message_) :
    header(header_),
    filename(filename_),
    function(function_),
    message(message_),
    line(line_),
    exceptionMessage(toString()) {}

  exception::~exception() throw() {}

  const char* exception::what() const throw() {
    return exceptionMessage.c_str();
  }

  std::string exception::toString(const int stackTraceStart) const {
    std::stringstream ss;

    // Pad message lines
    strVector lines = split(message, '\n');
    const int lineCount = (int) lines.size();

    for (int i = 0; i < lineCount; ++i) {
      if (i) {
        ss << "\n               ";
      }
      ss << lines[i];
    }
    const std::string prettyMessage = ss.str();
    ss.str("");

    std::string banner = "---[ " + header + " ]";
    ss << '\n'
       << banner << std::string(80 - banner.size(), '-') << '\n'
       << location()
       << "    Message  : " << prettyMessage << '\n'
       << "    Stack\n"
       << sys::stacktrace(stackTraceStart, "      ")
       << std::string(80, '=') << '\n';

    return ss.str();
  }

  std::string exception::location() const {
    std::stringstream ss;
    ss << "    File     : " << filename << '\n'
       << "    Line     : " << line     << '\n'
       << "    Function : " << function << '\n';
    return ss.str();
  }

  std::ostream& operator << (std::ostream& out,
                             const exception &exc)


#include <sstream>

#include <occa/utils/exception.hpp>
#include <occa/internal/utils/string.hpp>
#include <occa/internal/utils/sys.hpp>

namespace occa {
  exception::exception(const std::string &header_,
                       const std::string &filename_,
                       const std::string &function_,
                       const int line_,
                       const std::string &message_) :
    header(header_),
    filename(filename_),
    function(function_),
    message(message_),
    line(line_),
    exceptionMessage(toString()) {}

  exception::~exception() throw() {}

  const char* exception::what() const throw() {
    return exceptionMessage.c_str();
  }

  std::string exception::toString(const int stackTraceStart) const {
    std::stringstream ss;

    // Pad message lines
    strVector lines = split(message, '\

    const int lineCount = (int) lines.size();

    for (int i = 0; i < lineCount; ++i) {
      if (i) {
        ss << "\n               ";
      }
      ss << lines[i];
    }
    const std::string prettyMessage = ss.str();
    ss.str("");

    std::string banner = "---[ " + header + " ]";
    ss << '\n'
       << banner << std::string(80 - banner.size(), '-') << '\n'
       << location()
       << "    Message  : " << prettyMessage << '\n'
       << "    Stack\n"
       << sys::stacktrace(stackTraceStart, "      ")
       << std::string(80, '=') << '\n';

    return ss.str();
  }

  std::string exception::location() const {
    std::stringstream ss;
    ss << "    File     : " << filename << '\n'
       << "    Line     : " << line     << '\n'
       << "    Function : " << function << '\n';
    return ss.str();
  }

  std::ostream& operator << (std::ostream& out,
                             const exception &exc) {
    out << exc.toString() << std::flush;
    return out;
  }
}


/***
* ==++==
*
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* json.cpp
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/

#include "stdafx.h"
#include "./cpprest/json.h"

using namespace web;

bool json::details::g_keep_json_object_unsorted = false;
void json::keep_object_element_order(bool keep_order)
{
    json::details::g_keep_json_object_unsorted = keep_order;
}

utility::ostream_t& web::json::operator << (utility::ostream_t &os, const web::json::value &val)
{
    val.serialize(os);
    return os;
}

utility::istream_t& web::json::operator >> (utility::istream_t &is, json::value &val)
{
    val = json::value::parse(is);
    return is;
}

#pragma region json::value Constructors

web::json::value::value() :
    m_value(utility::details::make_unique<web::json::details::_Null>())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Null)
#endif
    { }

web::json::value::value(int32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(int64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(double value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(bool value) :
    m_value(utility::details::make_unique<web::json::details::_Boolean>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Boolean)
#endif
    { }

web::json::value::value(utility::string_t value) :
    m_value(utility::details::make_unique<web::json::details::_String>(std::move(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const utility::char_t* value) :
    m_value(utility::details::make_unique<web::json::details::_String>(utility::string_t(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const value &other) :
    m_value(other.m_value->_copy_value())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
    { }

web::json::value &web::json::value::operator=(const value &other)
{
    if(this != &other)
    {
        m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}
web::json::value::value(value &&other) :
    m_value(std::move(other.m_value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
{}

web::json::value &web::json::value::operator=(web::json::value &&other)
{
    if(this != &other)
    {
        m_value.swap(other.m_value);
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}

#pragma endregion

#pragma region Static Factories

web::json::value web::json::value::null()
{
    return web::json::value();
}

web::json::value web::json::value::number(double value)
{
    return web::json::value(value);
}

web::json::value web::json::value::number(int32_t value)
{
    return web::json::value(value);
}

web::json::value web::json::value::boolean(bool value)
{
    return web::json::value(value);
}

web::json::value web::json::value::string(utility::string_t value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(std::move(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}

#ifdef _MS_WINDOWS
web::json::value web::json::value::string(const std::string &value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(utility::conversions::to_utf16string(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}
#endif

web::json::value web::json::value::object(bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(std::move(fields), keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::array()
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>();
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(size_t size)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(size);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(std::vector<value> elements)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(std::move(elements));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

#pragma endregion

web::json::number web::json::value::as_number() const
{
    return m_value->as_number();
}

double web::json::value::as_double() const
{
    return m_value->as_double();
}

int web::json::value::as_integer() const
{
    return m_value->as_integer();
}

bool web::json::value::as_bool() const
{
    return m_value->as_bool();
}

json::array& web::json::value::as_array()
{
    return m_value->as_array();
}

const json::array& web::json::value::as_array() const
{
    return m_value->as_array();
}

json::object& web::json::value::as_object()
{
    return m_value->as_object();
}

const json::object& web::json::value::as_object() const
{
    return m_value->as_object();
}

#undef min
#undef max

bool web::json::number::is_int32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= std::numeric_limits<int32_t>::min() && m_intval <= std::numeric_limits<int32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<int32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_uint32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= 0 && m_intval <= std::numeric_limits<uint32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<uint32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_int64() const
{
    switch (m_type)
    {
    case signed_type : return true;
    case unsigned_type : return m_uintval <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
    case double_type :
    default :
        return false;
    }
}

bool web::json::details::_String::has_escape_chars(const _String &str)
{
    static const auto escapes = U("\"\\\b\f\r\n\t");
    return str.m_string.find_first_of(escapes) != utility::string_t::npos;
}

web::json::details::_Object::_Object(const _Object& other) :
    m_object(other.m_object.m_elements, other.m_object.m_keep_order), web::json::details::_Value(other) {}

web::json::value::value_type json::value::type() const { return m_value->type(); }

{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_integer();
}

bool json::value::is_double() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_double();
}

json::value& web::json::details::_Object::index(const utility::string_t &key)
{
    return m_object[key];
}

bool web::json::details::_Object::has_field(const utility::string_t &key) const
{
    return m_object.find(key) != m_object.end();
}

utility::string_t json::value::to_string() const { return m_value->to_string(); }

bool json::value::operator==(const json::value &other) const
{
    if (this->m_value.get() == other.m_value.get())
        return true;
    if (this->type() != other.type())
        return false;

    switch(this->type())
    {
    case Null:
        return true;
    case Number:
        return this->as_number() == other.as_number();
    case Boolean:
        return this->as_bool() == other.as_bool();
    case String:
        return this->as_string() == other.as_string();
    case Object:
        return static_cast<const json::details::_Object*>(this->m_value.get())->is_equal(static_cast<const json::details::_Object*>(other.m_value.get()));
    case Array:
        return static_cast<const json::details::_Array*>(this->m_value.get())->is_equal(static_cast<const json::details::_Array*>(other.m_value.get()));
    }
    UNREACHABLE;
}

web::json::value& web::json::value::at(size_t index)
{
    return this->as_array().at(index);
}

const web::json::value& web::json::value::at(size_t index) const
{
    return this->as_array().at(index);
}

web::json::value& web::json::value::at(const utility::string_t& key)
{
    return this->as_object().at(key);
}

const web::json::value& web::json::value::at(const utility::string_t& key) const
{
    return this->as_object().at(key);
}

web::json::value& web::json::value::operator [] (const utility::string_t &key)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Object(details::g_keep_json_object_unsorted));
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Object;
#endif
    }
    return m_value->index(key);
}

web::json::value& web::json::value::operator[](size_t index)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Array());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Array;
#endif
    }
    return m_value->index(index);
}


/***
* ==++==
*
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* json.cpp
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/

#include "stdafx.h"
#include "./cpprest/json.h"

using namespace web;

bool json::details::g_keep_json_object_unsorted = false;
void json::keep_object_element_order(bool keep_order)
{
    json::details::g_keep_json_object_unsorted = keep_order;
}

utility::ostream_t& web::json::operator << (utility::ostream_t &os, const web::json::value &val)
{
    val.serialize(os);
    return os;
}

utility::istream_t& web::json::operator >> (utility::istream_t &is, json::value &val)
{
    val = json::value::parse(is);
    return is;
}

#pragma region json::value Constructors

web::json::value::value() :
    m_value(utility::details::make_unique<web::json::details::_Null>())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Null)
#endif
    { }

web::json::value::value(int32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif

web::json::value::value(uint32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(int64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(double value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(bool value) :
    m_value(utility::details::make_unique<web::json::details::_Boolean>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Boolean)
#endif
    { }

web::json::value::value(utility::string_t value) :
    m_value(utility::details::make_unique<web::json::details::_String>(std::move(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const utility::char_t* value) :
    m_value(utility::details::make_unique<web::json::details::_String>(utility::string_t(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const value &other) :
    m_value(other.m_value->_copy_value())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
    { }

web::json::value &web::json::value::operator=(const value &other)
{
    if(this != &other)
    {
        m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}
web::json::value::value(value &&other) :
    m_value(std::move(other.m_value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
{}

web::json::value &web::json::value::operator=(web::json::value &&other)
{
    if(this != &other)
    {
        m_value.swap(other.m_value);
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}

#pragma endregion

#pragma region Static Factories

web::json::value web::json::value::null()
{
    return web::json::value();
}

web::json::value web::json::value::number(double value)
{
    return web::json::value(value);
}

web::json::value web::json::value::number(int32_t value)
{
    return web::json::value(value);
}

web::json::value web::json::value::boolean(bool value)
{
    return web::json::value(value);
}

web::json::value web::json::value::string(utility::string_t value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(std::move(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}

#ifdef _MS_WINDOWS
web::json::value web::json::value::string(const std::string &value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(utility::conversions::to_utf16string(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}
#endif

web::json::value web::json::value::object(bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(std::move(fields), keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::array()
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>();
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(size_t size)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(size);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(std::vector<value> elements)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(std::move(elements));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

#pragma endregion

web::json::number web::json::value::as_number() const
{
    return m_value->as_number();
}

double web::json::value::as_double() const
{
    return m_value->as_double();
}

int web::json::value::as_integer() const
{
    return m_value->as_integer();
}

bool web::json::value::as_bool() const
{
    return m_value->as_bool();
}

json::array& web::json::value::as_array()
{
    return m_value->as_array();
}

const json::array& web::json::value::as_array() const
{
    return m_value->as_array();
}

json::object& web::json::value::as_object()
{
    return m_value->as_object();
}

const json::object& web::json::value::as_object() const
{
    return m_value->as_object();
}

#undef min
#undef max

bool web::json::number::is_int32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= std::numeric_limits<int32_t>::min() && m_intval <= std::numeric_limits<int32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<int32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_uint32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= 0 && m_intval <= std::numeric_limits<uint32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<uint32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_int64() const
{
    switch (m_type)
    {
    case signed_type : return true;
    case unsigned_type : return m_uintval <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
    case double_type :
    default :
        return false;
    }
}

bool web::json::details::_String::has_escape_chars(const _String &str)
{
    static const auto escapes = U("\"\\\b\f\r\n\t");
    return str.m_string.find_first_of(escapes) != utility::string_t::npos;
}

web::json::details::_Object::_Object(const _Object& other) :
    m_object(other.m_object.m_elements, other.m_object.m_keep_order), web::json::details::_Value(other) {}

web::json::value::value_type json::value::type() const { return m_value->type(); }

bool json::value::is_integer() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_integer();
}

bool json::value::is_double() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_double();
}

json::value& web::json::details::_Object::index(const utility::string_t &key)
{
    return m_object[key];
}

bool web::json::details::_Object::has_field(const utility::string_t &key) const
{
    return m_object.find(key) != m_object.end();
}

utility::string_t json::value::to_string() const { return m_value->to_string(); }

bool json::value::operator==(const json::value &other) const
{
    if (this->m_value.get() == other.m_value.get())
        return true;
    if (this->type() != other.type())
        return false;

    switch(this->type())
    {
    case Null:
        return true;
    case Number:
        return this->as_number() == other.as_number();
    case Boolean:
        return this->as_bool() == other.as_bool();
    case String:
        return this->as_string() == other.as_string();
    case Object:
        return static_cast<const json::details::_Object*>(this->m_value.get())->is_equal(static_cast<const json::details::_Object*>(other.m_value.get()));
    case Array:
        return static_cast<const json::details::_Array*>(this->m_value.get())->is_equal(static_cast<const json::details::_Array*>(other.m_value.get()));
    }
    UNREACHABLE;
}

web::json::value& web::json::value::at(size_t index)
{
    return this->as_array().at(index);
}

const web::json::value& web::json::value::at(size_t index) const
{
    return this->as_array().at(index);
}

web::json::value& web::json::value::at(const utility::string_t& key)
{
    return this->as_object().at(key);
}

const web::json::value& web::json::value::at(const utility::string_t& key) const
{
    return this->as_object().at(key);
}

web::json::value& web::json::value::operator [] (const utility::string_t &key)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Object(details::g_keep_json_object_unsorted));
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Object;
#endif
    }
    return m_value->index(key);
}

web::json::value& web::json::value::operator[](size_t index)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Array());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Array;
#endif
    }
    return m_value->index(index);
}


/***
* ==++==
*
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* json.cpp
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/

#include "stdafx.h"
#include "./cpprest/json.h"

using namespace web;

bool json::details::g_keep_json_object_unsorted = false;
void json::keep_object_element_order(bool keep_order)
{
    json::details::g_keep_json_object_unsorted = keep_order;
}

utility::ostream_t& web::json::operator << (utility::ostream_t &os, const web::json::value &val)
{
    val.serialize(os);
    return os;
}

utility::istream_t& web::json::operator >> (utility::istream_t &is, json::value &val)
{
    val = json::value::parse(is);
    return is;
}

#pragma region json::value Constructors

web::json::value::value() :
    m_value(utility::details::make_unique<web::json::details::_Null>())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Null)
#endif
    { }

web::json::value::value(int32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(int64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(double value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(bool value) :
    m_value(utility::details::make_unique<web::json::details::_Boolean>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Boolean)
#endif
    { }

web::json::value::value(utility::string_t value) :
    m_value(utility::details::make_unique<web::json::details::_String>(std::move(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const utility::char_t* value) :
    m_value(utility::details::make_unique<web::json::details::_String>(utility::string_t(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const value &other) :
    m_value(other.m_value->_copy_value())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
    { }

web::json::value &web::json::value::operator=(const value &other)
{
    if(this != &other)
    {
        m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}
web::json::value::value(value &&other) :
    m_value(std::move(other.m_value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
{}

web::json::value &web::json::value::operator=(web::json::value &&other)
{
    if(this != &other)
    {
        m_value.swap(other.m_value);
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}

#pragma endregion

#pragma region Static Factories

web::json::value web::json::value::null()
{
    return web::json::value();
}

web::json::value web::json::value::number(double value)
{
    return web::json::value(value);
}

web::json::value web::json::value::number(int32_t value)
{
    return web::json::value(value);
}

web::json::value web::json::value::boolean(bool value)
{
    return web::json::value(value);
}

web::json::value web::json::value::string(utility::string_t value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(std::move(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}

#ifdef _MS_WINDOWS
web::json::value web::json::value::string(const std::string &value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(utility::conversions::to_utf16string(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}
#endif

web::json::value web::json::value::object(bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(std::move(fields), keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::array()
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>();
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(size_t size)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(size);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(std::vector<value> elements)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(std::move(elements));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

#pragma endregion

web::json::number web::json::value::as_number() const
{
    return m_value->as_number();
}

double web::json::value::as_double() const
{
    return m_value->as_double()

}

int web::json::value::as_integer() const
{
    return m_value->as_integer();
}

bool web::json::value::as_bool() const
{
    return m_value->as_bool();
}

json::array& web::json::value::as_array()
{
    return m_value->as_array();
}

const json::array& web::json::value::as_array() const
{
    return m_value->as_array();
}

json::object& web::json::value::as_object()
{
    return m_value->as_object();
}

const json::object& web::json::value::as_object() const
{
    return m_value->as_object();
}

#undef min
#undef max

bool web::json::number::is_int32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= std::numeric_limits<int32_t>::min() && m_intval <= std::numeric_limits<int32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<int32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_uint32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= 0 && m_intval <= std::numeric_limits<uint32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<uint32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_int64() const
{
    switch (m_type)
    {
    case signed_type : return true;
    case unsigned_type : return m_uintval <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
    case double_type :
    default :
        return false;
    }
}

bool web::json::details::_String::has_escape_chars(const _String &str)
{
    static const auto escapes = U("\"\\\b\f\r\n\t");
    return str.m_string.find_first_of(escapes) != utility::string_t::npos;
}

web::json::details::_Object::_Object(const _Object& other) :
    m_object(other.m_object.m_elements, other.m_object.m_keep_order), web::json::details::_Value(other) {}

web::json::value::value_type json::value::type() const { return m_value->type(); }

bool json::value::is_integer() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_integer();
}

bool json::value::is_double() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_double();
}

json::value& web::json::details::_Object::index(const utility::string_t &key)
{
    return m_object[key];
}

bool web::json::details::_Object::has_field(const utility::string_t &key) const
{
    return m_object.find(key) != m_object.end();
}

utility::string_t json::value::to_string() const { return m_value->to_string(); }

bool json::value::operator==(const json::value &other) const
{
    if (this->m_value.get() == other.m_value.get())
        return true;
    if (this->type() != other.type())
        return false;

    switch(this->type())
    {
    case Null:
        return true;
    case Number:
        return this->as_number() == other.as_number();
    case Boolean:
        return this->as_bool() == other.as_bool();
    case String:
        return this->as_string() == other.as_string();
    case Object:
        return static_cast<const json::details::_Object*>(this->m_value.get())->is_equal(static_cast<const json::details::_Object*>(other.m_value.get()));
    case Array:
        return static_cast<const json::details::_Array*>(this->m_value.get())->is_equal(static_cast<const json::details::_Array*>(other.m_value.get()));
    }
    UNREACHABLE;
}

web::json::value& web::json::value::at(size_t index)
{
    return this->as_array().at(index);
}

const web::json::value& web::json::value::at(size_t index) const
{
    return this->as_array().at(index);
}

web::json::value& web::json::value::at(const utility::string_t& key)
{
    return this->as_object().at(key);
}

const web::json::value& web::json::value::at(const utility::string_t& key) const
{
    return this->as_object().at(key);
}

web::json::value& web::json::value::operator [] (const utility::string_t &key)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Object(details::g_keep_json_object_unsorted));
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Object;
#endif
    }
    return m_value->index(key);
}

web::json::value& web::json::value::operator[](size_t index)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Array());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Array;
#endif
    }
    return m_value->index(index);
}


switch (m_type)
    {
    case signed_type : return m_intval >= 0 && m_intval <= std::numeric_limits<uint32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<uint32_t>::max();
    case double_type :
    default :
        return false;
    }

/***
* ==++==
*
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* json.cpp
*
* HTTP Library: JSON parser and writer
*
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/

#include "stdafx.h"
#include "./cpprest/json.h"

using namespace web;

bool json::details::g_keep_json_object_unsorted = false;
void json::keep_object_element_order(bool keep_order)
{
    json::details::g_keep_json_object_unsorted = keep_order;
}

utility::ostream_t& web::json::operator << (utility::ostream_t &os, const web::json::value &val)
{
    val.serialize(os);
    return os;
}

utility::istream_t& web::json::operator >> (utility::istream_t &is, json::value &val)
{
    val = json::value::parse(is);
    return is;
}

#pragma region json::value Constructors

web::json::value::value() :
    m_value(utility::details::make_unique<web::json::details::_Null>())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Null)
#endif
    { }

web::json::value::value(int32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint32_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(int64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(uint64_t value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(double value) :
    m_value(utility::details::make_unique<web::json::details::_Number>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Number)
#endif
    { }

web::json::value::value(bool value) :
    m_value(utility::details::make_unique<web::json::details::_Boolean>(value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::Boolean)
#endif
    { }

web::json::value::value(utility::string_t value) :
    m_value(utility::details::make_unique<web::json::details::_String>(std::move(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const utility::char_t* value) :
    m_value(utility::details::make_unique<web::json::details::_String>(utility::string_t(value)))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(value::String)
#endif
    { }

web::json::value::value(const value &other) :
    m_value(other.m_value->_copy_value())
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
    { }

web::json::value &web::json::value::operator=(const value &other)
{
    if(this != &other)
    {
        m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}
web::json::value::value(value &&other) :
    m_value(std::move(other.m_value))
#ifdef ENABLE_JSON_VALUE_VISUALIZER
    ,m_kind(other.m_kind)
#endif
{}

web::json::value &web::json::value::operator=(web::json::value &&other)
{
    if(this != &other)
    {
        m_value.swap(other.m_value);
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = other.m_kind;
#endif
    }
    return *this;
}

#pragma endregion

#pragma region Static Factories

web::json::value web::json::value::null()
{
    return web::json::value();
}

web::json::value web::json::value::number(double value)
{
    return web::json::value(value);
}

web::json::value web::json::value::number(int32_t value)
{
    return web::json::value(value);
}

web::json::value web::json::value::boolean(bool value)
{
    return web::json::value(value);
}

web::json::value web::json::value::string(utility::string_t value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(std::move(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}

#ifdef _MS_WINDOWS
web::json::value web::json::value::string(const std::string &value)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_String>(utility::conversions::to_utf16string(value));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::String
#endif
            );
}
#endif

web::json::value web::json::value::object(bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::object(std::vector<std::pair<::utility::string_t, value>> fields, bool keep_order)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Object>(std::move(fields), keep_order);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Object
#endif
            );
}

web::json::value web::json::value::array()
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>();
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(size_t size)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(size);
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

web::json::value web::json::value::array(std::vector<value> elements)
{
    std::unique_ptr<details::_Value> ptr = utility::details::make_unique<details::_Array>(std::move(elements));
    return web::json::value(std::move(ptr)
#ifdef ENABLE_JSON_VALUE_VISUALIZER
            ,value::Array
#endif
            );
}

#pragma endregion

web::json::number web::json::value::as_number() const
{
    return m_value->as_number();
}

double web::json::value::as_double() const
{
    return m_value->as_double();
}

int web::json::value::as_integer() const
{
    return m_value->as_integer();
}

bool web::json::value::as_bool() const
{
    return m_value->as_bool();
}

json::array& web::json::value::as_array()
{
    return m_value->as_array();
}

const json::array& web::json::value::as_array() const
{
    return m_value->as_array();
}

json::object& web::json::value::as_object()
{
    return m_value->as_object();
}

const json::object& web::json::value::as_object() const
{
    return m_value->as_object();
}

#undef min
#undef max

bool web::json::number::is_int32() const
{
    switch (m_type)
    {
    case signed_type : return m_intval >= std::numeric_limits<int32_t>::min() && m_intval <= std::numeric_limits<int32_t>::max();
    case unsigned_type : return m_uintval <= std::numeric_limits<int32_t>::max();
    case double_type :
    default :
        return false;
    }
}

bool web::json::number::is_uint32() const
{

}

bool web::json::number::is_int64() const
{
    switch (m_type)
    {
    case signed_type : return true;
    case unsigned_type : return m_uintval <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max());
    case double_type :
    default :
        return false;
    }
}

bool web::json::details::_String::has_escape_chars(const _String &str)
{
    static const auto escapes = U("\"\\\b\f\r\n\t");
    return str.m_string.find_first_of(escapes) != utility::string_t::npos;
}

web::json::details::_Object::_Object(const _Object& other) :
    m_object(other.m_object.m_elements, other.m_object.m_keep_order), web::json::details::_Value(other) {}

web::json::value::value_type json::value::type() const { return m_value->type(); }

bool json::value::is_integer() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_integer();
}

bool json::value::is_double() const
{
    if(!is_number())
    {
        return false;
    }
    return m_value->is_double();
}

json::value& web::json::details::_Object::index(const utility::string_t &key)
{
    return m_object[key];
}

bool web::json::details::_Object::has_field(const utility::string_t &key) const
{
    return m_object.find(key) != m_object.end();
}

utility::string_t json::value::to_string() const { return m_value->to_string(); }

bool json::value::operator==(const json::value &other) const
{
    if (this->m_value.get() == other.m_value.get())
        return true;
    if (this->type() != other.type())
        return false;

    switch(this->type())
    {
    case Null:
        return true;
    case Number:
        return this->as_number() == other.as_number();
    case Boolean:
        return this->as_bool() == other.as_bool();
    case String:
        return this->as_string() == other.as_string();
    case Object:
        return static_cast<const json::details::_Object*>(this->m_value.get())->is_equal(static_cast<const json::details::_Object*>(other.m_value.get()));
    case Array:
        return static_cast<const json::details::_Array*>(this->m_value.get())->is_equal(static_cast<const json::details::_Array*>(other.m_value.get()));
    }
    UNREACHABLE;
}

web::json::value& web::json::value::at(size_t index)
{
    return this->as_array().at(index);
}

const web::json::value& web::json::value::at(size_t index) const
{
    return this->as_array().at(index);
}

web::json::value& web::json::value::at(const utility::string_t& key)
{
    return this->as_object().at(key);
}

const web::json::value& web::json::value::at(const utility::string_t& key) const
{
    return this->as_object().at(key);
}

web::json::value& web::json::value::operator [] (const utility::string_t &key)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Object(details::g_keep_json_object_unsorted));
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Object;
#endif
    }
    return m_value->index(key);
}

web::json::value& web::json::value::operator[](size_t index)
{
    if ( this->is_null() )
    {
        m_value.reset(new web::json::details::_Array());
#ifdef ENABLE_JSON_VALUE_VISUALIZER
        m_kind = value::Array;
#endif
    }
    return m_value->index(index);
}


#include <valarray>
#include <cassert>
#include <cstddef>

{
    {
        typedef int T;
        T a1[] = {1,  2,  3,  4,  5};
        T a2[] = {6,  7,  8,  9, 10};
        T a3[] = {7,  5, 11, 13, 15};
        const unsigned N = sizeof(a1)/sizeof(a1[0]);
        std::valarray<T> v1(a1, N);
        std::valarray<T> v2(a2, N);
        std::valarray<T> v3(a3, N);
        v1 ^= v2;
        assert(v1.size() == v2.size());
        assert(v1.size() == v3.size());
        for (std::size_t i = 0; i < v1.size(); ++i)
            assert(v1[i] == v3[i]);
    }

  return 0;
}


#include <valarray>
#include <cassert>
#include <cstddef>

int main(int, char**)
{
    {
        typedef int T;
        T a1[] = {1,  2,  3,  4,  5};
        T a2[] = {6,  7,  8,  9, 10};
        T a3[] = {7,  5, 11, 13, 15};
        const unsigned N = sizeof(a1)/sizeof(a1[0]);
        std::valarray<T> v1(a1, N);
        std::valarray<T> v2(a2, N);
        std::valarray<T> v3(a3, N);
        v1 ^= v2;
        assert(v1.size() == v2.size());
        assert(v1.size() == v3.size());
        for (std::size_t i = 0; i < v1.size(); ++i)
            assert(v1[i] == v3[i]);
    }

  retu


void OnGameObjectCreate(GameObject* pGo, bool /*add*/)

/*
 * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
 *
 */

/* ScriptData
SDName: instance_uldaman
SD%Complete: 99%
SDComment: Need some cosmetics updates when archeadas door are closing (Guardians Waypoints).
SDCategory: Uldaman
EndScriptData */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "uldaman.h"

#define SPELL_ARCHAEDAS_AWAKEN        10347
#define SPELL_AWAKEN_VAULT_WALKER     10258

#define ARCHAEDAS_TEMPLE_DOOR           141869
#define ALTAR_OF_ARCHAEDAS              133234

#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367
#define ALTAR_OF_THE_KEEPER_TEMPLE      130511

#define ANCIENT_VAULT_DOOR              124369
#define IRONAYA_SEAL_DOOR               124372

#define KEYSTONE_GO                     124371

#define ENCOUNTERS 3

struct instance_uldaman : public ScriptedInstance
{
    instance_uldaman(Map* pMap) : ScriptedInstance(pMap)
    {
        Initialize();
    };

    void Initialize()
    {
        archaedasGUID = 0;
        ironayaGUID = 0;
        whoWokeArchaedasGUID = 0;

        altarOfTheKeeperTempleDoor = 0;
        archaedasTempleDoor = 0;
        ancientVaultDoor = 0;
        ironayaSealDoor = 0;

        keystoneGUID = 0;

        ironayaSealDoorTimer = 26000;
        keystoneCheck = false;

        for (uint8 i = 0; i < ENCOUNTERS; ++i)
            Encounters[i] = NOT_STARTED;

    }

    uint64 archaedasGUID;
    uint64 ironayaGUID;
    uint64 whoWokeArchaedasGUID;

    uint64 altarOfTheKeeperTempleDoor;
    uint64 archaedasTempleDoor;
    uint64 ancientVaultDoor;
    uint64 ironayaSealDoor;

    uint64 keystoneGUID;

    uint32 ironayaSealDoorTimer;
    bool keystoneCheck;

    std::vector<uint64> stoneKeeper;
    std::vector<uint64> altarOfTheKeeperCount;
    std::vector<uint64> vaultWalker;
    std::vector<uint64> earthenGuardian;
    std::vector<uint64> archaedasWallMinions;    // minions lined up around the wall

    uint32 Encounters[ENCOUNTERS];
    std::string str_data;

{
        switch (pGo->GetEntry())
        {
        case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR:         // lock the door
            altarOfTheKeeperTempleDoor = pGo->GetGUID();

            if (Encounters[0] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case ARCHAEDAS_TEMPLE_DOOR:
            archaedasTempleDoor = pGo->GetGUID();

            if (Encounters[0] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case ANCIENT_VAULT_DOOR:
            pGo->SetGoState(GO_STATE_READY);
            pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
            ancientVaultDoor = pGo->GetGUID();

            if (Encounters[1] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case IRONAYA_SEAL_DOOR:
            ironayaSealDoor = pGo->GetGUID();

            if (Encounters[2] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case KEYSTONE_GO:
            keystoneGUID = pGo->GetGUID();
            if (Encounters[2] == DONE)
            {
                HandleGameObject(0, true, pGo);
                pGo->SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
            }
            break;
        }
    }

    void SetFrozenState(Creature* pCreature)
    {
        pCreature->SetFaction(35);
        pCreature->RemoveAllAuras();
        pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
		pCreature->SetRooted(true);
    }

    void SetDoor(uint64 guid, bool open)
    {
        GameObject* pGo = instance->GetGameObject(guid);
        if (!pGo)
            return;

        HandleGameObject(0, open, pGo);
    }

    void BlockGO(uint64 guid)
    {
        GameObject* go = instance->GetGameObject(guid);
        if (!go)
            return;
        go->SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);

    }

    void ActivateStoneKeepers()
    {
        for (std::vector<uint64>::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || !pTarget->IsAlive() || pTarget->GetFaction() == 14)
                continue;
			pTarget->SetRooted(false);
            pTarget->SetFaction(14);
            pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            return;        // only want the first one we find
        }
        // if we get this far than all four are dead so open the door
        SetData (DATA_ALTAR_DOORS, DONE);
        SetDoor (archaedasTempleDoor, true); //open next the door too
    }

    void ActivateWallMinions()
    {
        Creature* archaedas = instance->GetCreature(archaedasGUID);
        if (!archaedas)
            return;

        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || !pTarget->IsAlive() || pTarget->GetFaction() == 14)
                continue;
            archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true);
            pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN, true);
            return;        // only want the first one we find
        }
    }

    // used when Archaedas dies.  All active minions must be despawned.
    void DeActivateMinions()
    {
        // first despawn any aggroed wall minions
        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }

        // Vault Walkers
        for (std::vector<uint64>::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }

        // Earthen Guardians
        for (std::vector<uint64>::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }
    }

    void ActivateArchaedas(uint64 target)
    {
        Creature* archaedas = instance->GetCreature(archaedasGUID);
        if (!archaedas)
            return;

        if (/*Unit* victim = */Unit::GetUnit(*archaedas, target))
        {
            archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN, false);
            whoWokeArchaedasGUID = target;
        }
    }

    void ActivateIronaya()
    {
        Creature* ironaya = instance->GetCreature(ironayaGUID);
        if (!ironaya)
            return;

        ironaya->SetFaction(415);
		ironaya->SetRooted(false);
        ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
    }

    void RespawnMinions()
    {
        // first respawn any aggroed wall minions
        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }

        // Vault Walkers
        for (std::vector<uint64>::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }

        // Earthen Guardians
        for (std::vector<uint64>::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }
    }

    void Update(uint32 diff)
    {
        if (!keystoneCheck)
            return;

        if (ironayaSealDoorTimer <= diff)
        {
            ActivateIronaya();

            SetDoor(ironayaSealDoor, true);
            BlockGO(keystoneGUID);

            SetData(DATA_IRONAYA_DOOR, DONE); //save state
            keystoneCheck = false;
        }
        else
            ironayaSealDoorTimer -= diff;
    }

    void SetData (uint32 type, uint32 data)
    {
        switch (type)
        {
        case DATA_ALTAR_DOORS:
            Encounters[0] = data;
            if (data == DONE)
                SetDoor (altarOfTheKeeperTempleDoor, true);
            break;

        case DATA_ANCIENT_DOOR:
            Encounters[1] = data;
            if (data == DONE) //archeadas defeat
            {
                SetDoor (archaedasTempleDoor, true); //re open enter door
                SetDoor (ancientVaultDoor, true);
            }
            break;

        case DATA_IRONAYA_DOOR:
            Encounters[2] = data;
            break;

        case DATA_STONE_KEEPERS:
            ActivateStoneKeepers();
            break;

        case DATA_MINIONS:
            switch (data)
            {
            case NOT_STARTED:
                if (Encounters[0] == DONE) //if players opened the doors
                    SetDoor (archaedasTempleDoor, true);

                RespawnMinions();
                break;
            case IN_PROGRESS:
                ActivateWallMinions();
                break;
            case SPECIAL:
                DeActivateMinions();
                break;
            }
            break;

        case DATA_IRONAYA_SEAL:
            keystoneCheck = true;
            break;
        }

        if (data == DONE)
        {
            OUT_SAVE_INST_DATA;

            std::ostringstream saveStream;
            saveStream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2];

            str_data = saveStream.str();

            SaveToDB();
            OUT_SAVE_INST_DATA_COMPLETE;
        }
    }

    void SetData64 (uint32 type, uint64 data)
    {
        // Archaedas
        if (type == 0)
        {
            ActivateArchaedas (data);
            SetDoor (archaedasTempleDoor, false); //close when event is started
        }
    }

    void OnCreatureCreate(Creature* pCreature, bool /*add*/)
    {
        switch (pCreature->GetEntry())
        {
        case 4857:    // Stone Keeper
            SetFrozenState (pCreature);
            stoneKeeper.push_back(pCreature->GetGUID());
            break;

        case 7309:    // Earthen Custodian
            archaedasWallMinions.push_back(pCreature->GetGUID());
            break;

        case 7077:    // Earthen Hallshaper
            archaedasWallMinions.push_back(pCreature->GetGUID());
            break;

        case 7076:    // Earthen Guardian
            earthenGuardian.push_back(pCreature->GetGUID());
            break;

        case 7228:    // Ironaya
            ironayaGUID = pCreature->GetGUID();

            if (Encounters[2] != DONE)
                SetFrozenState(pCreature);
            break;

        case 10120:   // Vault Walker
            vaultWalker.push_back(pCreature->GetGUID());
            break;

        case 2748:    // Archaedas
            archaedasGUID = pCreature->GetGUID();
            break;

        } // end switch
    } // end OnCreatureCreate

    uint64 GetData64 (uint32 identifier)
    {
        if (identifier == 0) return whoWokeArchaedasGUID;
        if (identifier == 1) return vaultWalker[0];    // VaultWalker1
        if (identifier == 2) return vaultWalker[1];    // VaultWalker2
        if (identifier == 3) return vaultWalker[2];    // VaultWalker3
        if (identifier == 4) return vaultWalker[3];    // VaultWalker4

        if (identifier == 5) return earthenGuardian[0];
        if (identifier == 6) return earthenGuardian[1];
        if (identifier == 7) return earthenGuardian[2];
        if (identifier == 8) return earthenGuardian[3];
        if (identifier == 9) return earthenGuardian[4];
        if (identifier == 10) return earthenGuardian[5];

        return 0;
    } // end GetData64

    std::string GetSaveData()
    {
        return str_data.c_str();
    }

    void Load(const char* in)
    {
        if (!in)
        {
            OUT_LOAD_INST_DATA_FAIL;
            return;
        }

        OUT_LOAD_INST_DATA(in);

        std::istringstream loadStream(in);
        loadStream >> Encounters[0] >> Encounters[1] >> Encounters[2];

        for (uint8 i = 0; i < ENCOUNTERS; ++i)
            if (Encounters[i] == IN_PROGRESS)
                Encounters[i] = NOT_STARTED;

        OUT_LOAD_INST_DATA_COMPLETE;
    }
};

InstanceData* GetInstanceData_instance_uldaman(Map* pMap)
{
    return new instance_uldaman(pMap);
}

void AddSC_instance_uldaman()
{
    Script* newscript;
    newscript = new Script;
    newscript->Name = "instance_uldaman";
    newscript->GetInstanceData = &GetInstanceData_instance_uldaman;
    newscript->RegisterSelf();
}


{
    Script* newscript;
    newscript = new Script;
    newscript->Name = "instance_uldaman";
    newscript->GetInstanceData = &GetInstanceData_instance_uldaman;
    newscript->RegisterSelf();
}

/*
 * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
 *
 */

/* ScriptData
SDName: instance_uldaman
SD%Complete: 99%
SDComment: Need some cosmetics updates when archeadas door are closing (Guardians Waypoints).
SDCategory: Uldaman
EndScriptData */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "uldaman.h"

#define SPELL_ARCHAEDAS_AWAKEN        10347
#define SPELL_AWAKEN_VAULT_WALKER     10258

#define ARCHAEDAS_TEMPLE_DOOR           141869
#define ALTAR_OF_ARCHAEDAS              133234

#define ALTAR_OF_THE_KEEPER_TEMPLE_DOOR 124367
#define ALTAR_OF_THE_KEEPER_TEMPLE      130511

#define ANCIENT_VAULT_DOOR              124369
#define IRONAYA_SEAL_DOOR               124372

#define KEYSTONE_GO                     124371

#define ENCOUNTERS 3

struct instance_uldaman : public ScriptedInstance
{
    instance_uldaman(Map* pMap) : ScriptedInstance(pMap)
    {
        Initialize();
    };

    void Initialize()
    {
        archaedasGUID = 0;
        ironayaGUID = 0;
        whoWokeArchaedasGUID = 0;

        altarOfTheKeeperTempleDoor = 0;
        archaedasTempleDoor = 0;
        ancientVaultDoor = 0;
        ironayaSealDoor = 0;

        keystoneGUID = 0;

        ironayaSealDoorTimer = 26000;
        keystoneCheck = false;

        for (uint8 i = 0; i < ENCOUNTERS; ++i)
            Encounters[i] = NOT_STARTED;

    }

    uint64 archaedasGUID;
    uint64 ironayaGUID;
    uint64 whoWokeArchaedasGUID;

    uint64 altarOfTheKeeperTempleDoor;
    uint64 archaedasTempleDoor;
    uint64 ancientVaultDoor;
    uint64 ironayaSealDoor;

    uint64 keystoneGUID;

    uint32 ironayaSealDoorTimer;
    bool keystoneCheck;

    std::vector<uint64> stoneKeeper;
    std::vector<uint64> altarOfTheKeeperCount;
    std::vector<uint64> vaultWalker;
    std::vector<uint64> earthenGuardian;
    std::vector<uint64> archaedasWallMinions;    // minions lined up around the wall

    uint32 Encounters[ENCOUNTERS];
    std::string str_data;

    void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
    {
        switch (pGo->GetEntry())
        {
        case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR:         // lock the door
            altarOfTheKeeperTempleDoor = pGo->GetGUID();

            if (Encounters[0] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case ARCHAEDAS_TEMPLE_DOOR:
            archaedasTempleDoor = pGo->GetGUID();

            if (Encounters[0] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case ANCIENT_VAULT_DOOR:
            pGo->SetGoState(GO_STATE_READY);
            pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
            ancientVaultDoor = pGo->GetGUID();

            if (Encounters[1] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case IRONAYA_SEAL_DOOR:
            ironayaSealDoor = pGo->GetGUID();

            if (Encounters[2] == DONE)
                HandleGameObject(0, true, pGo);
            break;

        case KEYSTONE_GO:
            keystoneGUID = pGo->GetGUID();
            if (Encounters[2] == DONE)
            {
                HandleGameObject(0, true, pGo);
                pGo->SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
            }
            break;
        }
    }

    void SetFrozenState(Creature* pCreature)
    {
        pCreature->SetFaction(35);
        pCreature->RemoveAllAuras();
        pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
		pCreature->SetRooted(true);
    }

    void SetDoor(uint64 guid, bool open)
    {
        GameObject* pGo = instance->GetGameObject(guid);
        if (!pGo)
            return;

        HandleGameObject(0, open, pGo);
    }

    void BlockGO(uint64 guid)
    {
        GameObject* go = instance->GetGameObject(guid);
        if (!go)
            return;
        go->SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);

    }

    void ActivateStoneKeepers()
    {
        for (std::vector<uint64>::const_iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || !pTarget->IsAlive() || pTarget->GetFaction() == 14)
                continue;
			pTarget->SetRooted(false);
            pTarget->SetFaction(14);
            pTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            return;        // only want the first one we find
        }
        // if we get this far than all four are dead so open the door
        SetData (DATA_ALTAR_DOORS, DONE);
        SetDoor (archaedasTempleDoor, true); //open next the door too
    }

    void ActivateWallMinions()
    {
        Creature* archaedas = instance->GetCreature(archaedasGUID);
        if (!archaedas)
            return;

        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || !pTarget->IsAlive() || pTarget->GetFaction() == 14)
                continue;
            archaedas->CastSpell(pTarget, SPELL_AWAKEN_VAULT_WALKER, true);
            pTarget->CastSpell(pTarget, SPELL_ARCHAEDAS_AWAKEN, true);
            return;        // only want the first one we find
        }
    }

    // used when Archaedas dies.  All active minions must be despawned.
    void DeActivateMinions()
    {
        // first despawn any aggroed wall minions
        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }

        // Vault Walkers
        for (std::vector<uint64>::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }

        // Earthen Guardians
        for (std::vector<uint64>::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (!pTarget || pTarget->isDead() || pTarget->GetFaction() != 14)
                continue;
            pTarget->setDeathState(JUST_DIED);
            pTarget->RemoveCorpse();
        }
    }

    void ActivateArchaedas(uint64 target)
    {
        Creature* archaedas = instance->GetCreature(archaedasGUID);
        if (!archaedas)
            return;

        if (/*Unit* victim = */Unit::GetUnit(*archaedas, target))
        {
            archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN, false);
            whoWokeArchaedasGUID = target;
        }
    }

    void ActivateIronaya()
    {
        Creature* ironaya = instance->GetCreature(ironayaGUID);
        if (!ironaya)
            return;

        ironaya->SetFaction(415);
		ironaya->SetRooted(false);
        ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
    }

    void RespawnMinions()
    {
        // first respawn any aggroed wall minions
        for (std::vector<uint64>::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }

        // Vault Walkers
        for (std::vector<uint64>::const_iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }

        // Earthen Guardians
        for (std::vector<uint64>::const_iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
        {
            Creature* pTarget = instance->GetCreature(*i);
            if (pTarget && pTarget->isDead())
            {
                pTarget->Respawn();
                pTarget->GetMotionMaster()->MoveTargetedHome();
                SetFrozenState(pTarget);
            }
        }
    }

    void Update(uint32 diff)
    {
        if (!keystoneCheck)
            return;

        if (ironayaSealDoorTimer <= diff)
        {
            ActivateIronaya();

            SetDoor(ironayaSealDoor, true);
            BlockGO(keystoneGUID);

            SetData(DATA_IRONAYA_DOOR, DONE); //save state
            keystoneCheck = false;
        }
        else
            ironayaSealDoorTimer -= diff;
    }

    void SetData (uint32 type, uint32 data)
    {
        switch (type)
        {
        case DATA_ALTAR_DOORS:
            Encounters[0] = data;
            if (data == DONE)
                SetDoor (altarOfTheKeeperTempleDoor, true);
            break;

        case DATA_ANCIENT_DOOR:
            Encounters[1] = data;
            if (data == DONE) //archeadas defeat
            {
                SetDoor (archaedasTempleDoor, true); //re open enter door
                SetDoor (ancientVaultDoor, true);
            }
            break;

        case DATA_IRONAYA_DOOR:
            Encounters[2] = data;
            break;

        case DATA_STONE_KEEPERS:
            ActivateStoneKeepers();
            break;

        case DATA_MINIONS:
            switch (data)
            {
            case NOT_STARTED:
                if (Encounters[0] == DONE) //if players opened the doors
                    SetDoor (archaedasTempleDoor, true);

                RespawnMinions();
                break;
            case IN_PROGRESS:
                ActivateWallMinions();
                break;
            case SPECIAL:
                DeActivateMinions();
                break;
            }
            break;

        case DATA_IRONAYA_SEAL:
            keystoneCheck = true;
            break;
        }

        if (data == DONE)
        {
            OUT_SAVE_INST_DATA;

            std::ostringstream saveStream;
            saveStream << Encounters[0] << " " << Encounters[1] << " " << Encounters[2];

            str_data = saveStream.str();

            SaveToDB();
            OUT_SAVE_INST_DATA_COMPLETE;
        }
    }

    void SetData64 (uint32 type, uint64 data)
    {
        // Archaedas
        if (type == 0)
        {
            ActivateArchaedas (data);
            SetDoor (archaedasTempleDoor, false); //close when event is started
        }
    }

    void OnCreatureCreate(Creature* pCreature, bool /*add*/)
    {
        switch (pCreature->GetEntry())
        {
        case 4857:    // Stone Keeper
            SetFrozenState (pCreature);
            stoneKeeper.push_back(pCreature->GetGUID());
            break;

        case 7309:    // Earthen Custodian
            archaedasWallMinions.push_back(pCreature->GetGUID());
            break;

        case 7077:    // Earthen Hallshaper
            archaedasWallMinions.push_back(pCreature->GetGUID());
            break;

        case 7076:    // Earthen Guardian
            earthenGuardian.push_back(pCreature->GetGUID());
            break;

        case 7228:    // Ironaya
            ironayaGUID = pCreature->GetGUID();

            if (Encounters[2] != DONE)
                SetFrozenState(pCreature);
            break;

        case 10120:   // Vault Walker
            vaultWalker.push_back(pCreature->GetGUID());
            break;

        case 2748:    // Archaedas
            archaedasGUID = pCreature->GetGUID();
            break;

        } // end switch
    } // end OnCreatureCreate

    uint64 GetData64 (uint32 identifier)
    {
        if (identifier == 0) return whoWokeArchaedasGUID;
        if (identifier == 1) return vaultWalker[0];    // VaultWalker1
        if (identifier == 2) return vaultWalker[1];    // VaultWalker2
        if (identifier == 3) return vaultWalker[2];    // VaultWalker3
        if (identifier == 4) return vaultWalker[3];    // VaultWalker4

        if (identifier == 5) return earthenGuardian[0];
        if (identifier == 6) return earthenGuardian[1];
        if (identifier == 7) return earthenGuardian[2];
        if (identifier == 8) return earthenGuardian[3];
        if (identifier == 9) return earthenGuardian[4];
        if (identifier == 10) return earthenGuardian[5];

        return 0;
    } // end GetData64

    std::string GetSaveData()
    {
        return str_data.c_str();
    }

    void Load(const char* in)
    {
        if (!in)
        {
            OUT_LOAD_INST_DATA_FAIL;
            return;
        }

        OUT_LOAD_INST_DATA(in);

        std::istringstream loadStream(in);
        loadStream >> Encounters[0] >> Encounters[1] >> Encounters[2];

        for (uint8 i = 0; i < ENCOUNTERS; ++i)
            if (Encounters[i] == IN_PROGRESS)
                Encounters[i] = NOT_STARTED;

        OUT_LOAD_INST_DATA_COMPLETE;
    }
};

InstanceData* GetInstanceData_instance_uldaman(Map* pMap)
{
    return new instance_uldaman(pMap);
}

void AddSC_instance_uldaman()