/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include "Exception.h"
#include <decaf/util/logging/LoggerDefines.h>
#include <decaf/internal/AprPool.h>

#include <sstream>
#include <apr_strings.h>

using namespace std;
using namespace decaf;
using namespace decaf::internal;
using namespace decaf::lang;
using namespace decaf::util::logging;

////////////////////////////////////////////////////////////////////////////////
Exception::Exception() throw() : Throwable(), cause( NULL ) {
}

////////////////////////////////////////////////////////////////////////////////
Exception::Exception( const Exception& ex ) throw() : Throwable(), cause( NULL ) {
    *this = ex;
}

////////////////////////////////////////////////////////////////////////////////
Exception::Exception( const std::exception* cause ) throw() : Throwable(), cause( NULL ) {
    this->initCause( cause );
}

////////////////////////////////////////////////////////////////////////////////
Exception::Exception( const char* file, const int lineNumber,
                      const char* msg, ... ) throw() : Throwable(), cause( NULL ) {
    va_list vargs;
    va_start( vargs, msg ) ;
    buildMessage( msg, vargs );
    va_end( vargs );

    // Set the first mark for this exception.
    setMark( file, lineNumber );
}

////////////////////////////////////////////////////////////////////////////////
Exception::Exception( const char* file, const int lineNumber,
                      const std::exception* cause,
                      const char* msg, ... ) throw() : Throwable(), cause( NULL ) {
    va_list vargs;
    va_start( vargs, msg ) ;
    this->buildMessage( msg, vargs );
    va_end( vargs );

    // Store the cause
    this->initCause( cause );

    // Set the first mark for this exception.
    this->setMark( file, lineNumber );
}

////////////////////////////////////////////////////////////////////////////////
Exception::~Exception() throw(){
    delete this->cause;
}

////////////////////////////////////////////////////////////////////////////////
void Exception::setMessage( const char* msg, ... ){
    va_list vargs;
    va_start( vargs, msg );
    buildMessage( msg, vargs );
    va_end( vargs );
}

////////////////////////////////////////////////////////////////////////////////
void Exception::buildMessage( const char* format, va_list& vargs ) {

    // Allocate buffer with a guess of it's size
    AprPool pool;

    // Allocate a buffer of the specified size.
    char* buffer = apr_pvsprintf( pool.getAprPool(), format, vargs );

    // Guessed size was enough. Assign the string.
    message.assign( buffer, strlen( buffer ) );
}

////////////////////////////////////////////////////////////////////////////////
void Exception::setMark( const char* file, const int lineNumber ) {

    // Add this mark to the end of the stack trace.
    stackTrace.push_back( std::make_pair( (std::string)file, (int)lineNumber ) );

    std::ostringstream stream;
    stream << "\tFILE: " << stackTrace[stackTrace.size()-1].first;
    stream << ", LINE: " << stackTrace[stackTrace.size()-1].second;

    //decaf::util::logger::SimpleLogger logger("com.yadda2");
    //logger.log( stream.str() );
}

////////////////////////////////////////////////////////////////////////////////
Exception* Exception::clone() const {
    return new Exception( *this );
}

////////////////////////////////////////////////////////////////////////////////
std::vector< std::pair< std::string, int> > Exception::getStackTrace() const {
    return stackTrace;
}

////////////////////////////////////////////////////////////////////////////////
void Exception::setStackTrace(
    const std::vector< std::pair< std::string, int> >& trace ) {

    this->stackTrace = trace;
}

////////////////////////////////////////////////////////////////////////////////
void Exception::printStackTrace() const {
    printStackTrace( std::cerr );
}

////////////////////////////////////////////////////////////////////////////////
void Exception::printStackTrace( std::ostream& stream ) const {
    stream << getStackTraceString();
}

////////////////////////////////////////////////////////////////////////////////
std::string Exception::getStackTraceString() const {

    // Create the output stream.
    std::ostringstream stream;

    // Write the message and each stack entry.
    stream << message << std::endl;
    for( unsigned int ix=0; ix<stackTrace.size(); ++ix ){
        stream << "\tFILE: " << stackTrace[ix].first;
        stream << ", LINE: " << stackTrace[ix].second;
        stream << std::endl;
    }

    // Return the string from the output stream.
    return stream.str();
}

////////////////////////////////////////////////////////////////////////////////
Exception& Exception::operator =( const Exception& ex ){
    this->message = ex.message;
    this->stackTrace = ex.stackTrace;
    this->initCause( ex.cause );
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
void Exception::initCause( const std::exception* cause ) {

    if( cause == NULL || cause == this ) {
        return;
    }

    const Exception* ptrCause = dynamic_cast<const Exception*>( cause );
    if( ptrCause == NULL ) {
        this->cause = new Exception( __FILE__, __LINE__, cause->what() );
    } else {
        this->cause = ptrCause->clone();
    }

    if( this->message == "" ) {
        this->message = cause->what();
    }
}
