#  PMail - GNOME/GTK/Python email client
#  Copyright (C) 2000 Scott Bender <sbender@harmony-ds.com>

#  This file is part of PMail.

#  PMail is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2, or (at your option)
#  any later version.

#  PMail is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.

#  You should have received a copy of the GNU General Public License
#  along with GNU Emacs; see the file COPYING.  If not, write to
#  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#  Boston, MA 02111-1307, USA.  

from gtk import *
import GtkExtra
import string

import config
import Base
import mail
import gutil
import update

class Window(GtkScrolledWindow, Base.PMailObject):
  def __init__(self, mainWindow, listWindow):
    GtkScrolledWindow.__init__(self)
    Base.PMailObject.__init__(self, debug=0)
    self.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)

    self._listWindow = listWindow
    self._mainWindow = mainWindow
    self._tree = None
    self._selected_mailbox = None
    self._disable_list_update = 0

    self._column_headers = ['Name', 'Total', 'Unread']
    defsizes = [100, 10, 10]
    self._column_headers_sizes = config.getWindowParam(self,
                                                       'column_headers_sizes',
                                                       defsizes)
    self._tree = GtkCTree(3, 0, self._column_headers)
    self.add(self._tree)

    self._tree.connect('button_press_event', self.button_press_event)
    self._tree.connect_after('tree_select_row', self.tree_row_selected)
    self._tree.connect("resize_column", self.column_resized)
    self._tree.connect("tree_expand", self.tree_expand)
    self._tree.connect("tree_collapse", self.tree_collapse)
    
    self._tree.connect('drag_data_received', self.drag_data_received)
    self._tree.connect('drag_motion', self.drag_motion)
    self._tree.connect('drag_leave', self.drag_leave)
    self._tree.drag_dest_set(DEST_DEFAULT_ALL,
                             [('application/x-pmail', 0, -1)],
                             GDK.ACTION_COPY|GDK.ACTION_MOVE)
      
    for i in range(len(self._column_headers)):
      self._tree.set_column_width(i, self._column_headers_sizes[i])
      
    self.update_tree()
    self._tree.show()

  def drag_data_received(self, widget, context, x, y, data, info, time):
    #print 'drag_data_received:', widget, context, x, y, data, info, time
    s = data.data

    msgs = string.split(s, '\n')
    for s in msgs:
      if len(s):
        msg = string.split(s, ',')
        source = mail.source_with_unique_id(string.atoi(msg[0]))
        box = source.mailbox_with_path(msg[1])
        msg = box.message_with_id(string.atoi(msg[2]))
        selected = self._tree.get_selection_info(x, y);
        if selected:
          node = self._tree.node_nth(selected[0]-1)
          tobox = self._tree.node_get_row_data(node)

          self.debug('DRAG: %s{%s}.%d(%s) -> %s{%s}' % \
                     (source.name(), box.name(), msg.id(),
                      msg, tobox.source().name(),
                      tobox.name()))

          msg.append(tobox)

    self._tree.drag_finish(context, 1, 0, time)
    self.update()

  def drag_motion(self, widget, context, x, y, time):
    selected = self._tree.get_selection_info(x, y);
    if selected:
      row = selected[0]-1
      self._disable_list_update = 1    
      self._tree.select_row(row, 0)

  def drag_leave(self, widget, context, time):
    if self._selected_mailbox:
      self.select_mailbox(self._selected_mailbox)
    self._disable_list_update = 0
                  

  def column_resized(self, clist, col, width):
    self._column_headers_sizes[col] = width

  def store_config(self):
    config.setWindowParam(self, 
                          'column_headers_sizes',
                          self._column_headers_sizes)
    

  def name(self):
    return 'TreeWindow'

  def tree_expand(self, tree, node):
    data = self._tree.node_get_row_data(node)
    data['expanded'] = 1

  def tree_collapse(self, tree, node):
    data = self._tree.node_get_row_data(node)
    data['expanded'] = 0
  
  def __add_mailboxes(self, node, boxes):
    if boxes and len(boxes):
      self.debug('adding mailboxes: %s' % boxes)

      boxes = list(boxes)
      def box_sort(l, r):
        ls = l.path()
        rs = r.path()
        if ls == rs:
          return 0
        elif ls > rs:
          return 1
        else:
          return -1

      boxes.sort(box_sort)      

      for box in boxes:
        leaf = len(box.mailboxes()) == 0
        cnt = '%d' % box.message_count()
        unr = '%d' % box.unseen_count()
        expand = box['expanded']
        if expand == None:
          expand = 0
        n = self._tree.insert_node(node, None, [box.name(), cnt, unr],
                                   is_leaf=leaf,
                                   expanded = expand)
        self._tree.node_set_row_data(n, box)
        self._row_count = self._row_count + 1
        self.__add_mailboxes(n, box.mailboxes())
        

  def update_tree(self):
    sources = mail.get_sources()

    self._tree.freeze()
    self._tree.clear()

    self._row_count = 0
    
    for source in sources:
      self.debug('adding source: %s' % source.name())
      source['ui'] = self._mainWindow

      if not source['show']:
        continue
      expand = source['expanded'] 
      if expand == None:
        expand = 1
      n = self._tree.insert_node(None, None, [source.name(), '', ''],
                                 is_leaf=FALSE,
                                 expanded=expand)
      self._tree.node_set_row_data(n, source)
      self._row_count = self._row_count + 1
      self.__add_mailboxes(n, source.mailboxes())

    #add one extra cause clist-get_selection_info must have a bug
    #it won't give me the last item in the tree
    n = self._tree.insert_node(None, None, ['', '', ''],
                               is_leaf=TRUE)
    self._tree.node_set_selectable(n, 0)

    self.update_colors()
    self._tree.thaw()

  def update_colors(self):
    for i in range(self._row_count):
      node = self._tree.node_nth(i)
      if node:
        data = self._tree.node_get_row_data(node)
        if isinstance(data, mail.Mailbox):
          fg = self._listWindow._normalfor_color
          bg = self._listWindow._normalback_color
          if data.unseen_count():
            c = self._listWindow._unread_color
            if self._listWindow._unread_forb:
              fg = c
            else:
              bg = c
          self._tree.node_set_foreground(node, fg)
          self._tree.node_set_background(node, bg)        

  def update(self):
    self._tree.freeze()
    for i in range(self._row_count):
      node = self._tree.node_nth(i)
      if node:
        data = self._tree.node_get_row_data(node)
        if isinstance(data, mail.Mailbox):
          self._tree.node_set_text(node, 1, '%d' % data.message_count())
          self._tree.node_set_text(node, 2, '%d' % data.unseen_count())
        self.update_colors()
    self._tree.thaw()

  def select_mailbox(self, box):
    node = self._tree.find_by_row_data(None, box)
    self._tree.select(node)

  def tree_row_selected(self, tree, node, col):
    if not self._disable_list_update:
      data = self._tree.node_get_row_data(node)
      if isinstance(data, mail.Mailbox) and data.is_selectable():
        self._selected_mailbox = data
        #update.update() #let the tree update for the selection
        self._listWindow.list_messages(data, is_selection=1)
        self.update()
        
  def button_press_event(self, w, event):
    #print 'button_press_event:', w, event
    if event.button != 3:
      return
    
    selected =  w.get_selection_info(event.x, event.y)
    if selected:
      row = selected[0]
      node = self._tree.node_nth(row)
      box = self._tree.node_get_row_data(node)

      if not box:
        return

      mf = GtkExtra.MenuFactory(GtkExtra.MENU_FACTORY_MENU)
      entries = []

      if box.can_add_subfolder():
        entries.append(('Add Subfolder...', None, self.add_subfolder, box))
        
      if box.can_delete():
        entries.append(('Delete Folder', None, self.delete_folder, box))

      if box.can_rename():
        entries.append(('Rename Folder...', None, self.rename_folder, box))

      if len(entries):
        entries.append(('<separator>', None, None))

      if box.can_expunge():
        entries.append(('Expunge Folder', None, self.expunge_folder, box))
        
      entries.append(('Check for new mail', None, self.check_mail, box))

      mf.add_entries(entries)
      menu = mf.get_menu('')
      menu.popup(None, None, None, event.button, event.time)

  def add_subfolder(self, d, box):
    name = gutil.input_box(box.name(), 'New folder name:')
    if name:
      box.create_subfolder(name)
      self.update_tree()

  def delete_folder(self, d, box):
    if gutil.question_box('Delete', "Are you sure you want to delete '%s'" %
                       box.path()):
      box.delete()
      self.update_tree()

  def rename_folder(self, d, box):
    name = gutil.input_box(box.name(), 'Enter the new folder name:',
                           box.path())
    if name:
      box.rename(name)

  def expunge_folder(self, d, box):
    box.expunge()
    if box == self._listWindow._mailbox:
      self._listWindow.list_messages()
    self.update_tree()

  def check_mail(self, d, box):
    if box.check_mail():
      if box == self._listWindow._mailbox:
        self._listWindow.list_messages()
      self.update()
      
      

      
        
