#   Copyright (c) 2006-2008 Open Source Applications Foundation
#
#   Licensed 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.

# 10-10-2011 Niels Zeilemaker: modified version of http://svn.osafoundation.org/chandler/trunk/chandler/application/feedback.py

import sys
import os
import wx
from Tribler.Main.vwxGUI.GuiUtility import GUIUtility
import platform
from Tribler.Main.vwxGUI.tribler_topButton import AutoWidthListCtrl
import httplib
from urllib import urlencode

class FeedbackWindow(wx.PyOnDemandOutputWindow):
    """
    An error dialog that would be shown in case there is an uncaught
    exception. The user can send the error report back to us as well.
    """
    def __call__(self, *args, **kw):
        # Make this a Singleton to avoid the problem of multiple feedback
        # windows popping up at the same time
        return self

    def _fillOptionalSection(self):
        try:    
            # columns
            self.sysInfo.InsertColumn(0, 'key')
            self.sysInfo.InsertColumn(1, 'value')

            def add(col, val):
                pos = self.sysInfo.InsertStringItem(sys.maxint, col)
                self.sysInfo.SetStringItem(pos, 1, val)

            # data
            add('os.getcwd', '%s' % os.getcwd())
            add('sys.executable', '%s' % sys.executable)
            
            add('os',os.name)
            add('platform',sys.platform)
            add('platform.details',platform.platform())
            add('platform.machine', platform.machine())
            add('python.version',sys.version)
            add('indebug', str(__debug__))
            
            for argv in sys.argv:
                add('sys.argv', '%s' % argv)
                
            for path in sys.path:
                add('sys.path', '%s' % path)
                
            for key in os.environ.keys():
                add('os.environ', '%s: %s' % (key, os.environ[key]))
                
            #read tribler.log?
#            try:
#                
#                f = codecs.open(os.path.join(Globals.options.profileDir,
#                                             'chandler.log'),
#                                encoding='utf-8', mode='r', errors='ignore')
#                for line in f.readlines()[-LOGLINES:]:
#                    self.frame.sysInfo.InsertStringItem(index, 'chandler.log')
#                    self.frame.sysInfo.SetStringItem(index, 1, '%s' % line.strip())
#                    index += 1
#            except:
#                pass
            
        except:
            pass
        
        self.sysInfo.SetColumnWidth(0, wx.LIST_AUTOSIZE)
        self.sysInfo.SetColumnWidth(1, wx.LIST_AUTOSIZE)

    def _fillRequiredSection(self, st):
        # Version and other miscellaneous information
        try:
            guiUtility = GUIUtility.getInstance()
            utility = guiUtility.utility
            
            self.text.AppendText('%s version: %s\n' %(utility.lang.get('title'), utility.lang.get('version')))
        except:
            pass
        
        # Traceback (actually just the first line of it)
        self.text.AppendText(st)

    def CreateOutputWindow(self, st):
        self.frame = wx.Dialog(self.parent, -1, self.title, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
        
        self.frame.CenterOnParent()
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        
        icon = wx.StaticBitmap(self.frame, -1, wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_MESSAGE_BOX))
        sizer.Add(icon)
        
        vSizer = wx.BoxSizer(wx.VERTICAL)
        vSizer.Add(wx.StaticText(self.frame, -1, 'Tribler encountered an error, to help us fix this please send an error-report.'))
        
        self.text = wx.TextCtrl(self.frame, -1, "", style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.text.SetMinSize((600, 150))
        vSizer.Add(self.text, 0, wx.EXPAND)
        
        self.sysInfo = AutoWidthListCtrl(self.frame, style = wx.LC_REPORT|wx.NO_BORDER)
        self.sysInfo.SetMinSize((-1, 200))
        vSizer.Add(self.sysInfo, 1, wx.EXPAND)
        
        self.comments = wx.TextCtrl(self.frame, -1, "", style=wx.TE_MULTILINE)
        self.comments.SetMinSize((-1, 100))
        vSizer.Add(wx.StaticText(self.frame, -1, 'Comments: (optional)'))
        vSizer.Add(self.comments, 0, wx.EXPAND)
        
        self.email = wx.TextCtrl(self.frame, -1, "")
        vSizer.Add(wx.StaticText(self.frame, -1, 'Email: (optional)'))
        vSizer.Add(self.email, 0, wx.EXPAND)
        
        buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
        
        self.sendButton = wx.Button(self.frame, -1, 'Send Report')
        self.sendButton.Bind(wx.EVT_BUTTON, self.OnSend)
        buttonSizer.Add(self.sendButton, 0, wx.RIGHT, 3)
        
        if self.parent:
            self.restartButton = wx.Button(self.frame, -1, 'Restart')
            self.restartButton.Bind(wx.EVT_BUTTON, self.OnRestart)
            buttonSizer.Add(self.restartButton, 0, wx.RIGHT, 3)
            
        self.closeButton = wx.Button(self.frame, wx.ID_CANCEL)
        self.closeButton.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
        buttonSizer.Add(self.closeButton)
        
        vSizer.Add(buttonSizer, 0, wx.ALIGN_RIGHT|wx.TOP, 10)
        sizer.Add(vSizer, 1, wx.EXPAND|wx.LEFT, 10)
        
        self._fillRequiredSection(st)
        self._fillOptionalSection()
        
        self.frame.Bind(wx.EVT_CHAR, self.OnChar)
        self.frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        
        border = wx.BoxSizer()
        border.Add(sizer, 1, wx.ALL|wx.EXPAND, 10)
        
        self.frame.SetSizerAndFit(border)

    def OnChar(self, event):
        # Close the window if an escape is typed
        keycode = event.GetKeyCode()
        if keycode == wx.WXK_ESCAPE:
            self.OnCloseWindow(event)
        else:
            event.Skip()
            
    def OnRestart(self, event):
        try:
            self.sendButton.Disable()
            self.restartButton.Disable()
            self.closeButton.Disable() 
            self.restartButton.SetLabel('Restarting...')
            
            self.parent.Restart()
            
        finally:
            self.frame.Show(False)

    def OnSend(self, event):
        self.sendButton.Disable()
        
        # Disabling the focused button disables keyboard navigation
        # unless we set the focus to something else - let's put it
        # on close button
        self.closeButton.SetFocus() 
        self.sendButton.SetLabel('Sending...')
        
        try:
            c = httplib.HTTPConnection('dispersyreporter.tribler.org')
            
            email = 'Not provided'
            if self.email.GetValue():
                email = self.email.GetValue()
            
            comments = 'Not provided'
            if self.comments.GetValue():
                comments = self.comments.GetValue()
            
            body_dict = {'email':email, 'comments':comments}
            body_dict['stack'] = self.text.GetValue()
            
            optional = ''
            for i in range(self.sysInfo.GetItemCount()):
                field = self.sysInfo.GetItem(i, 0).GetText()
                value = self.sysInfo.GetItem(i, 1).GetText()
                optional += field + '\t' + value + '\n'
            body_dict['sysinfo'] = optional
            
            body = urlencode(body_dict)
            
            c.request('POST', '/exception.py', body)
            response = c.getresponse()
            
            if response.status != 200:
                raise Exception('response.status=' + response.status)
            c.close()
        except:
            self.sendButton.SetLabel('Failed to send')
        else:
            self.sendButton.SetLabel('Sent')
            
    def Show(self, show = True):
        return self.frame.Show(show)
    
    def ShowModal(self):
        return self.frame.ShowModal()