##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

from queue import Queue
from collections import deque

from lisp.utils import configuration as cfg

from PyQt4.QtCore import QThread, pyqtSignal


class Action():

    isReversible = True

    hasInfo = False

    def exec_(self):
        actionHandler.register(self)

    def do(self):
        pass

    def undo(self):
        pass

    def redo(self):
        pass

    def info(self):
        return ''


class ActionHandler(QThread):

    __actionQueue = Queue()

    __undoStack = deque()
    __redoStack = deque()

    infoSignal = pyqtSignal(str)

    stacksMaxSize = int(cfg.config['Actions']['StacksSize'])

    enableInfoPrint = cfg.config['Actions']['PrintInfo'] == 'True'
    enableinfoEmit = cfg.config['Actions']['EmitInfo'] == 'True'

    def __init__(self):
        super(ActionHandler, self).__init__()

    def register(self, action):
        if(isinstance(action, Action)):
            ActionHandler.__actionQueue.put(action)

    def undo(self):
        if(len(ActionHandler.__undoStack) > 0):
            action = ActionHandler.__undoStack.pop()
            action.undo()
            self.__info(action, 'Undo: ')
            self.__arrangeStack(self.__redoStack)
            ActionHandler.__redoStack.append(action)

    def redo(self):
        if(len(ActionHandler.__redoStack) > 0):
            action = ActionHandler.__redoStack.pop()
            action.redo()
            self.__info(action, 'Redo: ')
            ActionHandler.__undoStack.append(action)

    def run(self):
        while(True):
            action = ActionHandler.__actionQueue.get()
            action.do()
            self.__info(action, 'Last action: ')
            if(action.isReversible):
                self.__arrangeStack(self.__undoStack)
                ActionHandler.__undoStack.append(action)
                ActionHandler.__redoStack.clear()

    def __arrangeStack(self, stack):
        if(self.stacksMaxSize > 0 and len(stack) == self.stacksMaxSize):
            stack.popleft()

    def __info(self, action, pre='', post=''):
        if(action.hasInfo):
            if(self.enableInfoPrint):
                print(pre, action.info(), post)
            if(self.enableinfoEmit):
                self.infoSignal.emit(pre + action.info() + post)

actionHandler = ActionHandler()
#actionHandler.setDaemon(True)
actionHandler.start()
