# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------
# Copyright (c) 2009  Jendrik Seipp
# 
# RedNotebook 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 of the License, or
# (at your option) any later version.
# 
# RedNotebook 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 RedNotebook; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# -----------------------------------------------------------------------

import logging

class Action(object):
	def __init__(self, undo_function, redo_function, tags):
		self.undo_function = undo_function
		self.redo_function = redo_function
		self.tags = tags

class UndoRedoManager(object):
	size = 100
	buffer = 20
	def __init__(self, main_window):
		self.main_window = main_window
		#self.undo_menu_item = self.main_window.builder.get_object('undo_menuitem')
		#self.redo_menu_item = self.main_window.builder.get_object('redo_menuitem')
		
		self.undo_menu_item = self.main_window.uimanager.get_widget('/MainMenuBar/Edit/Undo')
		self.redo_menu_item = self.main_window.uimanager.get_widget('/MainMenuBar/Edit/Redo')
		
		self.undo_stack = []
		self.redo_stack = []
		
		self.update_buttons()
		
	
	def add_action(self, action):
		'''
		Arguments are functions that encode what there is to to to redo and undo
		the action
		'''
		self.undo_stack.append(action)
		
		# Delete some items, if the undo stack grows too big
		if len(self.undo_stack) > self.size + self.buffer:
			del self.undo_stack[:self.buffer]
		
		# When a new action has been made, forget all redos
		del self.redo_stack[:]
		
		self.update_buttons()
		
	def undo(self, *args):
		if not self.can_undo():
			logging.info('There is nothing to undo')
			return
		
		logging.debug('Undo')
		
		action = self.undo_stack.pop()
		action.undo_function()
		self.redo_stack.append(action)
		
		self.update_buttons()
		
	def redo(self, *args):
		if not self.can_redo():
			logging.info('There is nothing to redo')
			return
		
		logging.debug('Redo')
		
		action = self.redo_stack.pop()
		action.redo_function()
		self.undo_stack.append(action)
		
		self.update_buttons()
		
	def can_undo(self):
		return len(self.undo_stack) > 0
	
	def can_redo(self):
		return len(self.redo_stack) > 0
	
	def delete_actions(self, tag):
		self.undo_stack = filter(lambda action: not tag in action.tags, self.undo_stack)
		self.redo_stack = filter(lambda action: not tag in action.tags, self.redo_stack)
		
		self.update_buttons()
		
	def update_buttons(self):
		self.undo_menu_item.set_sensitive(self.can_undo())
		self.redo_menu_item.set_sensitive(self.can_redo())
		
	def clear(self):
		del self.undo_stack[:]
		del self.redo_stack[:]
		self.update_buttons()
	
		