import ini, packets
import os, time
from PyQt4 import QtCore, QtGui
from bisect import bisect_left

class DemoPlayer(QtCore.QObject):
    MS_Chat = QtCore.pyqtSignal(list)
    newChar = QtCore.pyqtSignal(str)
    newBackground = QtCore.pyqtSignal(str, bool)
    IC_Log = QtCore.pyqtSignal(str)
    OOC_Log = QtCore.pyqtSignal(str)
    charSlots = QtCore.pyqtSignal()
    allEvidence = QtCore.pyqtSignal(list)
    rainbowColor = QtCore.pyqtSignal(str)
    updatePlayerList = QtCore.pyqtSignal(str, int, int, str)
    timerUpdate = QtCore.pyqtSignal(int, int, int)
    
    def __init__(self, parent):
        super(DemoPlayer, self).__init__(parent)
        self.parent = parent
        self.paused = False
        self.demo = []
        self.demo_length = len(self.demo)
        self.time = 0
        self.demo_length_ms = 0
        self.wait_timer = QtCore.QTimer(self)
        self.wait_timer.setSingleShot(True)
        self.wait_timer.timeout.connect(self.timer_done)
        
        self.mc = [] # Music changes
        self.bn = [] # Background changes
        self.last_music = ""
        self.last_bg = ""
    
    def start(self, file):
        self.paused = True
        self.wait_timer.stop()
        
        self.time = 0
        self.demo_length_ms = 0
        self.demo = []
        self.mc = []
        self.bn = []
        self.last_music = ""
        self.last_bg = ""
        self.load_demo(file)
        print "[client] Started demo playback (%s commands)" % self.demo_length
        
        self.parent.demoslider.setMaximum(self.demo_length - 1)
        self.OOC_Log.emit("<b>Demo playback started.</b>")
        
        secs = self.demo_length_ms / 1000
        mins = secs / 60
        hours = mins / 60
        self.OOC_Log.emit("Approximate duration: %02d:%02d:%02d." % (hours, mins % 60, secs % 60))
        
        self.OOC_Log.emit("")
        self.step()
        
    def playpause(self):
        self.paused = not self.paused
        if not self.paused and self.time < self.demo_length:
            self.step()
        
    def step(self, skip_wait=False):
        if self.time >= self.demo_length:
            self.time = 0
            return
            
        packet = self.demo[self.time]
        self.parent.demoslider.blockSignals(True)
        self.parent.demoslider.setValue(self.time)
        self.parent.demoslider.blockSignals(False)
        self.time += 1
        self.paused = False
        
        if packet[0] == "wait":
            if skip_wait:
                self.time += 1
            else:
                self.wait_timer.start(int(packet[1]))
                return
            
        packets.handle_packets(self, [packet], False)
        if self.time < self.demo_length:
            self.wait_timer.start(1)
        else:
            self.OOC_Log.emit("<b>Demo playback finished.</b>")
    
    def seek(self, time):
        self.parent.inbox_timer.stop()
        self.parent.inboxqueue = []
        self.wait_timer.stop()
        self.time = time
        
        mc_times = [t[0] for t in self.mc]
        t = bisect_left(mc_times, self.time) - 1
        if t >= 0:
            music = self.mc[t][1][1] 
            if music != self.last_music:
                packets.handle_packets(self, [self.mc[t][1]], False)
                self.last_music = music
        
        bn_times = [t[0] for t in self.bn]
        t = bisect_left(bn_times, self.time) - 1
        if t >= 0:
            bg = self.bn[t][1][1]
            if bg != self.last_bg:
                packets.handle_packets(self, [self.bn[t][1]], False)
                self.last_bg = bg
                
        self.step()
                
    def load_demo(self, file):
        last_line = ""
        time = 0
        with open(file) as f:
            for line in f:
                last_line = last_line + line
                if last_line.strip()[-1] == "%":
                    packet = last_line.split("#")[:-1]
                    self.demo.append(packet)
                    if packet[0] == "MC":
                        self.mc.append((time, packet))
                    elif packet[0] == "BN":
                        self.bn.append((time, packet))
                    elif packet[0] == "wait":
                        self.demo_length_ms += int(packet[1])
                    last_line = ""
                    time += 1
        self.demo_length = len(self.demo)
    
    def timer_done(self):
        if self.paused:
            return
        self.step()
    
    def stop(self):
        self.paused = True
        self.wait_timer.stop()

class DemoRecorder():
    def __init__(self):
        self.demofile = None
        self.lasttime = 0
            
    def start(self):
        if not os.path.exists("logs"):
            os.mkdir("logs")
        
        currtime = time.localtime()
        self.lasttime = time.time() * 1000
        self.demofile = "logs/%d-%02d-%02d %02d.%02d.%02d.demo" % (currtime[0], currtime[1], currtime[2], currtime[3], currtime[4], currtime[5])
    
    def record(self, packet, encode=False):
        if packet[0][0] in ["FM", "ARUP", "CharsCheck"]:
            return
        
        #print packet[0][0]
        with open(self.demofile, "a") as demofile:
            currtime = time.time() * 1000
            diff = currtime - self.lasttime
            self.lasttime = currtime
            demofile.write(("wait#%d#%%" % diff) + "\n")
            
            line = "#".join(packet[0]) + "#%\n"
            if encode:
                line = line.encode('utf-8')
            demofile.write(line)
            
class DemoPicker(QtGui.QDialog):
    def __init__(self, parent):
        super(DemoPicker, self).__init__()
        self.setModal(True)
        self.gamewindow = parent
        self.parent = parent
        
        self.setWindowTitle("Select a demo file...")
        self.setFixedSize(480, 512)
        self.setWindowIcon(QtGui.QIcon("AO2XP.ico"))
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
        self.hide()
        
        self.treeview = get_demo_treeview()
        self.treeview.doubleClicked.connect(self.on_demo_click)
        
        self.cancelbtn = QtGui.QPushButton()
        self.cancelbtn.setText("Cancel")
        self.cancelbtn.clicked.connect(self.hide)
        
        main_layout = QtGui.QVBoxLayout(self)
        btns_layout = QtGui.QHBoxLayout()
        
        btns_layout.addWidget(self.cancelbtn, 0, QtCore.Qt.AlignRight)
        
        main_layout.addWidget(self.treeview)
        main_layout.addLayout(btns_layout)
        
        self.cancelbtn.setFocus()
        
    def on_demo_click(self, item):
        fname = get_demo_fname(self.treeview, item)
        
        if not fname:
            return
            
        self.gamewindow.gamewidget.start_demo(fname)
        self.gamewindow.stackwidget.setCurrentWidget(self.gamewindow.gamewidget)
        self.hide()

def get_demo_treeview():
    demo_model = QtGui.QFileSystemModel();
    demo_model.setRootPath("logs");
    demo_model.setFilter(QtCore.QDir.Files | QtCore.QDir.AllDirs | QtCore.QDir.NoDotAndDotDot)
    demo_model.setNameFilters(QtCore.QStringList("*.demo"))
    demo_model.setNameFilterDisables(False)
    demo_treeview = QtGui.QTreeView()
    demo_treeview.setHeaderHidden(True)
    demo_treeview.setModel(demo_model);
    demo_treeview.setRootIndex(demo_model.index("logs"));
    for i in range(1, demo_model.columnCount()):
        demo_treeview.hideColumn(i)
        
    return demo_treeview
    
def get_demo_fname(treeview, item):
    model = treeview.model()
    if model.isDir(item):
        return None

    path = QtCore.QStringList()

    while item.isValid():
        fname = model.fileName(item)
        if fname == "logs":
            path.insert(0, "logs")
            break
        path.insert(0, fname)
        item = item.parent()

    return path.join("/")