// ################################
// ##   Hlaseni chyb a vyjimek   ##
// ##jejich osetrovani a logovani##
// ################################

#include "error_handling.h"
#include <cstdarg>
#include <iostream>

// ################################
// ################################

#ifdef _DEBUG
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#endif

#define ERR_BUFSIZE 1024

std :: ostream& err_output = std :: cerr;

// --------------------------------

static std :: string onlyFile(const std :: string& file)
{
    return file.substr(file.find_last_of("\\")+1);
}

// --------------------------------

void __exception_error(const std :: string& fname, const std :: string& func, int line, const std :: string desc, ...)
{
    err_output << onlyFile(fname) << ", " << func << ", " << line << ": ";

    va_list argptr;
    va_start(argptr, desc);

    std :: string :: const_iterator iter = desc.begin(); 
    while (iter != desc.end())
    {
        if (*iter != '%') 
        {
            err_output << *iter;
        }
        else 
        {
            iter++;
            if (iter != desc.end())
            {
                switch (*iter)
                {
                case 'i':   err_output << va_arg(argptr, long);                 break;
                case 'c':   err_output << va_arg(argptr, char);                 break;
                case 'd':   err_output << va_arg(argptr, double);               break;
                case 'l':   err_output << va_arg(argptr, long long);            break;
                case 's':   err_output << va_arg(argptr, char*);                break;
                case 'S':   err_output << va_arg(argptr, std :: string);        break;
                case 'u':   err_output << va_arg(argptr, unsigned long long);   break;   
                default:
                    err_output << "##ARGERR";
                }
            }
        }

        iter++;
    }

    va_end(argptr);

    err_output << std :: endl;
}

// --------------------------------

void __logical_error(const std :: string& fname, const std :: string& func, int line, const std :: string desc, ...)
{
    err_output << onlyFile(fname) << ", " << func << ", " << line << ": ";

    va_list argptr;
    va_start(argptr, desc);

    std :: string :: const_iterator iter = desc.begin(); 
    while (iter != desc.end())
    {
        if (*iter != '%') 
        {
            err_output << *iter;
        }
        else 
        {
            iter++;
            if (iter != desc.end())
            {
                switch (*iter)
                {
                case 'i':   err_output << va_arg(argptr, long);                 break;
                case 'c':   err_output << va_arg(argptr, char);                 break;
                case 'd':   err_output << va_arg(argptr, double);               break;
                case 'l':   err_output << va_arg(argptr, long long);            break;
                case 's':   err_output << va_arg(argptr, char*);                break;
                case 'S':   err_output << va_arg(argptr, std :: string);        break;
                case 'u':   err_output << va_arg(argptr, unsigned long long);   break;   
                default:
                    err_output << "##ARGERR";
                }
            }
        }

        iter++;
    }

    va_end(argptr);

    err_output << std :: endl;
}

// --------------------------------


// ################################
// ################################