# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.

"""
Exception handler that's able to extract detailled error informations
and write them to a file.
"""

__maintainer__ = "Benjamin Kampmann <benjamin@fluendo.com>"

import os, sys, cgitb
import traceback, tempfile
from cStringIO import StringIO

def format_failure(failure, detail='default'):
    """
    Format a failure into a human readable string (containing line-breaks).

    @param failure:     the twisted failure that should get formatted
    @type failure:      L{twisted.internet.python.failure.Failure}
    @keyword detail:    the detail-level, proxied to
                        L{twisted.internet.python.failure.Failure.printTraceback}
    @type detail:       string    

    @rtype:     string
    @return:    the formatted traceback.
    """
    io = StringIO()
    # FIXME: read the frames like cgitb.text is doing it
    failure.printTraceback(file=io, detail=detail)
    return io.getvalue()

def format_traceback(*args):
    """
    Format a traceback into a human readable string (containing line-breaks).
    If three arguments are given, they are expected to be the type of the
    Exceptiong, the Exception itself and the Traceback-Object (in this order).
    If no values are given (or the length is not 3), use sys.exc_info() to get
    these informations.

    @rtype:     string
    @return:    the formatted traceback.
    """   
    if len(args) == 3:
        info = args
    else:
        info = sys.exc_info()

    try:
        return cgitb.text(info, 5)
    except:
        # return something usefull even if it fails
        return ''.join(traceback.format_exception(*info))
 
def write_to_logfile(data, logdir = None):
    """
    Write data to a new tempfile in the given logdir and return the path to
    the new file.

    @param data:        the data to write down
    @type data:         string or unicode
    @keyword logdir:    the path to the directory to log into. if None the
                        default system temp dir is used.
    @type logdir:       string        

    @rtype:  string
    @return: The path to the new file or None if it didn't work
    """

    if logdir is not None and not os.path.exists(logdir):
        try:
            os.makedirs(logdir)
        except OSError, e:
            # avoid to have same error in the future by setting logdir
            # to None
            print "Could not make directory %r: %r", logdir, e
            traceback.print_exc()
            return None

    try:
        (fd, path) = tempfile.mkstemp(suffix='.txt', prefix="elisa_",
                                  dir=logdir)
    except OSError, e:
        print "Could not open tempfile in %r: %r", logdir, e
        traceback.print_exc()
        return None

    try:
        file = os.fdopen(fd, 'w')
        file.write(data)
        file.close()
    except:
        print "Tried to write a traceback to file %s but it failed:" % path
        traceback.print_exc()
        return None

    return path
