from ConfigParserEdit import ConfigParser
from os.path import exists
from os import listdir, _exit
import subprocess
try:
    import Cocoa # mac
except: pass

from PyQt4 import QtGui, QtCore
from constants import *

import ini

class Settings(QtGui.QDialog):
    def __init__(self, parent):
        super(Settings, self).__init__()
        self.setModal(True)
        self.gamewindow = parent
        self.parent = parent
        
        self.inifile = ConfigParser()
        self.setWindowTitle("AO2XP Settings")
        self.setFixedSize(480, 512)
        self.setWindowIcon(QtGui.QIcon("AO2XP.ico"))
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)
        self.hide()
        
        main_layout = QtGui.QVBoxLayout(self)
        save_layout = QtGui.QHBoxLayout()
        
        self.tabs = QtGui.QTabWidget()
        self.tabs.resize(320-16, 480-40)
        self.tabs.move(8, 8)
        
        general_tab = QtGui.QWidget()
        audio_tab = QtGui.QWidget()
        callwords_tab = QtGui.QWidget()
        general_layout = QtGui.QVBoxLayout(general_tab)
        general_layout.setAlignment(QtCore.Qt.AlignTop)
        audio_layout = QtGui.QFormLayout(audio_tab)
        audio_layout.setLabelAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
        audio_layout.setFormAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        callwords_layout = QtGui.QVBoxLayout(callwords_tab)
        callwords_layout.setAlignment(QtCore.Qt.AlignTop)
        
        self.savebtn = QtGui.QPushButton()
        self.savebtn.setText("Save")
        self.savebtn.clicked.connect(self.onSaveClicked)
        self.cancelbtn = QtGui.QPushButton()
        self.cancelbtn.setText("Cancel")
        self.cancelbtn.clicked.connect(self.onCancelClicked)
        self.aboutbtn = QtGui.QPushButton()
        self.aboutbtn.setText("About...")
        self.aboutbtn.clicked.connect(self.onAboutClicked)
        
        separators = []
        for i in range(5):
            separator = QtGui.QFrame()
            separator.setFixedSize(separator.size().width(), 12)
            separators.append(separator)
        
        ###### General tab ######
        defaultoocname_layout = QtGui.QHBoxLayout()
        defaultoocname_label = QtGui.QLabel("Default OOC name")
        self.defaultoocname = QtGui.QLineEdit()
        defaultoocname_layout.addWidget(defaultoocname_label)
        defaultoocname_layout.addWidget(self.defaultoocname)

        defaultshowname_label = QtGui.QLabel("Default showname")
        self.defaultshowname = QtGui.QLineEdit()
        defaultoocname_layout.addWidget(defaultshowname_label)
        defaultoocname_layout.addWidget(self.defaultshowname)
        
        savetolog_layout = QtGui.QHBoxLayout()
        self.savetolog = QtGui.QCheckBox()
        self.savetolog.setText("Save chat logs to a file")
        self.savetolog.setChecked(False)
        self.savetolog_combine = QtGui.QCheckBox()
        self.savetolog_combine.setText("Combine OOC and IC chat logs in the same file")
        self.savetolog_combine.setChecked(False)
        savetolog_layout.addWidget(self.savetolog)
        savetolog_layout.addWidget(self.savetolog_combine)
        
        savedemos_layout = QtGui.QHBoxLayout()
        self.savedemos = QtGui.QCheckBox()
        self.savedemos.setText("Record demo files")
        self.savedemos.setChecked(False)
        savedemos_layout.addWidget(self.savedemos)
                
        textstaytime_layout = QtGui.QHBoxLayout()
        textstaytime_label = QtGui.QLabel("Text stay time (milliseconds)")
        self.textstaytime = QtGui.QSpinBox()
        self.textstaytime.setMinimum(0)
        self.textstaytime.setMaximum(10000)
        textstaytime_layout.addWidget(textstaytime_label)
        textstaytime_layout.addWidget(self.textstaytime)
        
        slide_layout = QtGui.QHBoxLayout()
        self.enableslide = QtGui.QCheckBox()
        self.enableslide.setText("(Experimental) Display courtroom slide (pan-tilt) animations")
        self.enableslide.setChecked(True)
        slide_layout.addWidget(self.enableslide)
        
        allowdownload = QtGui.QLabel()
        allowdownload.setText("Automatically download or stream online from WebAO:")
        allowdownload_layout = QtGui.QHBoxLayout()
        self.allowdownload_chars = QtGui.QCheckBox("Characters")
        self.allowdownload_sounds = QtGui.QCheckBox("Sounds")
        self.allowdownload_music = QtGui.QCheckBox("Music")
        self.allowdownload_evidence = QtGui.QCheckBox("Evidence")
        allowdownload_layout.addWidget(self.allowdownload_chars)
        allowdownload_layout.addWidget(self.allowdownload_sounds)
        allowdownload_layout.addWidget(self.allowdownload_music)
        allowdownload_layout.addWidget(self.allowdownload_evidence)

        currtheme_layout = QtGui.QHBoxLayout()
        currtheme_label = QtGui.QLabel("Current theme")
        self.currtheme = QtGui.QComboBox()
        self.themes = listdir(AO2XPpath+"ao2xp_themes")
        for theme in self.themes:
            if exists(AO2XPpath+"ao2xp_themes/"+theme+"/theme.py"):
                self.currtheme.addItem(theme)
        currtheme_layout.addWidget(currtheme_label)
        currtheme_layout.addWidget(self.currtheme)
        
        autoconnect_layout = QtGui.QHBoxLayout()
        autoconnect_label = QtGui.QLabel("Connect automatically to this server")
        self.autoconnect = QtGui.QComboBox()

        autopick_layout = QtGui.QHBoxLayout()
        autopick_label = QtGui.QLabel("Pick this character automatically on join")
        self.autopick = QtGui.QComboBox()
        for folder in listdir(unicode(AOpath + 'characters')):
            if exists(AOpath + 'characters/' + folder + '/char.ini'):
                self.autopick.addItem(folder)
        self.autopick.setEditable(1)

        autopick_layout.addWidget(autopick_label)
        autopick_layout.addWidget(self.autopick)

        autojoinarea_layout = QtGui.QHBoxLayout()
        autojoinarea_label = QtGui.QLabel("Go to this area automatically on join")
        self.autojoinarea = QtGui.QLineEdit()
        autojoinarea_layout.addWidget(autojoinarea_label)
        autojoinarea_layout.addWidget(self.autojoinarea)

        self.autoconnect.addItem("Always show server list")
        if exists(AOpath+'serverlist.txt'):
            with open(AOpath+'serverlist.txt') as file:
                for server in [line.rstrip().split(':') for line in file]:
                    self.autoconnect.addItem(server[-1])
        autoconnect_layout.addWidget(autoconnect_label)
        autoconnect_layout.addWidget(self.autoconnect)

        update_layout = QtGui.QHBoxLayout()
        self.check_updates = QtGui.QCheckBox("Check for AO2XP updates on startup")
        self.check_updates_btn = QtGui.QPushButton()
        self.check_updates_btn.setText("Check now...")
        self.check_updates_btn.clicked.connect(self.onUpdateClicked)
        update_layout.addWidget(self.check_updates)
        update_layout.addWidget(self.check_updates_btn)
        
        general_layout.addLayout(defaultoocname_layout)
        general_layout.addLayout(savetolog_layout)
        general_layout.addLayout(savedemos_layout)
        general_layout.addWidget(separators[0])
        general_layout.addLayout(textstaytime_layout)
        general_layout.addLayout(slide_layout)
        general_layout.addWidget(separators[1])
        general_layout.addLayout(currtheme_layout)
        general_layout.addLayout(autoconnect_layout)
        general_layout.addLayout(autopick_layout)
        general_layout.addLayout(autojoinarea_layout)
        general_layout.addWidget(separators[2])
        general_layout.addWidget(allowdownload)
        general_layout.addLayout(allowdownload_layout)
        general_layout.addWidget(separators[3])
        general_layout.addLayout(update_layout)

        ###### Audio tab ######
        device_label = QtGui.QLabel("Audio device")
        self.device_list = QtGui.QComboBox()
        audio_layout.setWidget(0, QtGui.QFormLayout.LabelRole, device_label)
        audio_layout.setWidget(0, QtGui.QFormLayout.FieldRole, self.device_list)
        audio_layout.setWidget(1, QtGui.QFormLayout.FieldRole, separators[4])

        volumelabel = QtGui.QLabel("Sound volume")
        musiclabel = QtGui.QLabel("Music")
        soundlabel = QtGui.QLabel("Sounds")
        bliplabel = QtGui.QLabel("Blips")
        self.musicslider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.soundslider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.blipslider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
        self.musicslider.setRange(0, 100)
        self.soundslider.setRange(0, 100)
        self.blipslider.setRange(0, 100)
        audio_layout.setWidget(2, QtGui.QFormLayout.LabelRole, musiclabel)
        audio_layout.setWidget(2, QtGui.QFormLayout.FieldRole, self.musicslider)
        audio_layout.setWidget(3, QtGui.QFormLayout.LabelRole, soundlabel)
        audio_layout.setWidget(3, QtGui.QFormLayout.FieldRole, self.soundslider)
        audio_layout.setWidget(4, QtGui.QFormLayout.LabelRole, bliplabel)
        audio_layout.setWidget(4, QtGui.QFormLayout.FieldRole, self.blipslider)

        self.reloadaudio = QtGui.QPushButton(text="Reload audio system")
        self.reloadaudio.clicked.connect(self.onReloadAudio)
        audio_layout.setWidget(5, QtGui.QFormLayout.FieldRole, self.reloadaudio)

        for device in audio.getdevices():
            self.device_list.addItem(device)

        ###### Callwords tab ######
        self.callwords_edit = QtGui.QTextEdit()
        
        callwords_wordwrap = QtGui.QCheckBox("Word Wrap")
        callwords_wordwrap.setChecked(True)
        callwords_wordwrap.stateChanged.connect(self.callwordsWordWrapCheckbox)
        
        callwords_instructions = QtGui.QLabel()
        callwords_instructions.setText("Separate callwords with newlines (ENTER key).")
        
        callwords_layout.addWidget(self.callwords_edit)
        callwords_layout.addWidget(callwords_wordwrap, 0, QtCore.Qt.AlignRight)
        callwords_layout.addWidget(callwords_instructions)
        
        self.tabs.addTab(general_tab, "General")
        self.tabs.addTab(audio_tab, "Audio")
        self.tabs.addTab(callwords_tab, "Callwords")
        
        save_layout.addWidget(self.savebtn, 100, QtCore.Qt.AlignRight)
        save_layout.addWidget(self.cancelbtn, 0, QtCore.Qt.AlignRight)
        save_layout.addWidget(self.aboutbtn, 0, QtCore.Qt.AlignLeft)
        main_layout.addWidget(self.tabs)
        main_layout.addLayout(save_layout)
        
        self.savebtn.setFocus()
        
        # If they're different from the respective checkbox on save, tell the gui to start/stop logging
        self.savelogs_state = False
        self.combinelogs_state = False
        self.savedemos_state = False
    
    def showSettings(self):
        if exists("AO2XP.ini"):
            self.inifile.read("AO2XP.ini")
            self.savetolog.setChecked(ini.read_ini_bool(self.inifile, "General", "save logs", False))
            self.savetolog_combine.setChecked(ini.read_ini_bool(self.inifile, "General", "combined logs", False))
            self.savedemos.setChecked(ini.read_ini_bool(self.inifile, "General", "record demos", False))
            try:
                self.defaultoocname.setText(ini.read_ini(self.inifile, "General", "OOC name").decode("utf-8"))
            except:
                self.defaultoocname.setText(ini.read_ini(self.inifile, "General", "OOC name"))
            try:
                self.defaultshowname.setText(ini.read_ini(self.inifile, "General", "showname").decode("utf-8"))
            except:
                self.defaultshowname.setText(ini.read_ini(self.inifile, "General", "showname"))
            self.enableslide.setChecked(ini.read_ini_bool(self.inifile, "General", "slide", False))
            self.allowdownload_chars.setChecked(ini.read_ini_bool(self.inifile, "General", "download characters"))
            self.allowdownload_sounds.setChecked(ini.read_ini_bool(self.inifile, "General", "download sounds"))
            self.allowdownload_music.setChecked(ini.read_ini_bool(self.inifile, "General", "download music"))
            self.allowdownload_evidence.setChecked(ini.read_ini_bool(self.inifile, "General", "download evidence"))
            self.currtheme.setCurrentIndex(self.themes.index(ini.read_ini(self.inifile, "General", "theme", "default")))
            self.autoconnect.setCurrentIndex(ini.read_ini_int(self.inifile, "General", "auto connect", -1) + 1)
            self.autopick.setEditText(ini.read_ini(self.inifile, "General", "auto pick").decode('utf-8'))
            self.autojoinarea.setText(ini.read_ini(self.inifile, "General", "auto join area").decode('utf-8'))
            self.textstaytime.setValue(ini.read_ini_int(self.inifile, "General", "text stay time", 200))

            self.check_updates.setChecked(ini.read_ini_bool(self.inifile, "General", "install updates", False)) # Automatic updates are opt-in!

            self.device_list.setCurrentIndex(ini.read_ini_int(self.inifile, "Audio", "device", audio.getcurrdevice()))
            self.musicslider.setValue(ini.read_ini_int(self.inifile, "Audio", "Music volume", 100))
            self.soundslider.setValue(ini.read_ini_int(self.inifile, "Audio", "Sound volume", 100))
            self.blipslider.setValue(ini.read_ini_int(self.inifile, "Audio", "Blip volume", 100))
        else:
            self.savetolog.setChecked(False)
            self.savetolog_combine.setChecked(False)
            self.savedemos.setChecked(False)
            self.defaultoocname.setText("")
            self.defaultshowname.setText("")
            self.enableslide.setChecked(False)
            self.allowdownload_sounds.setChecked(True)
            self.allowdownload_music.setChecked(True)
            self.allowdownload_evidence.setChecked(True)
            self.currtheme.setCurrentIndex(self.themes.index("default"))
            self.check_updates.setChecked(False)
            self.textstaytime.setValue(200)
            self.autopick.setEditText("")
            self.autojoinarea.setText("")

            self.device_list.setCurrentIndex(audio.getcurrdevice())
            self.musicslider.setValue(100)
            self.soundslider.setValue(100)
            self.blipslider.setValue(100)
        
        self.callwords_edit.clear()
        if exists(AO2XPpath+"callwords.ini"):
            with open(AO2XPpath+"callwords.ini") as f:
                for line in f:
                    self.callwords_edit.append(line.rstrip().decode("utf-8"))
        
        self.savelogs_state = self.savetolog.isChecked()
        self.combinelogs_state = self.savetolog_combine.isChecked()
        self.savedemos_state = self.savedemos.isChecked()
        
        self.tabs.setCurrentIndex(0)
        self.show()
    
    def callwordsWordWrapCheckbox(self, newstate):
        if newstate:
            self.callwords_edit.setWordWrapMode(QtGui.QTextOption.WrapAtWordBoundaryOrAnywhere)
        else:
            self.callwords_edit.setWordWrapMode(0)
    
    def onSaveClicked(self):
        if not self.inifile.has_section("General"): self.inifile.add_section("General")
        if not self.inifile.has_section("Audio"): self.inifile.add_section("Audio")
        self.inifile.set("General", "save logs", self.savetolog.isChecked())
        self.inifile.set("General", "combined logs", self.savetolog_combine.isChecked())
        self.inifile.set("General", "record demos", self.savedemos.isChecked())
        self.inifile.set("General", "OOC name", self.defaultoocname.text().toUtf8())
        self.inifile.set("General", "showname", self.defaultshowname.text().toUtf8())
        self.inifile.set("General", "text stay time", self.textstaytime.value())
        self.inifile.set("General", "slide", self.enableslide.isChecked())
        self.inifile.set("General", "download characters", self.allowdownload_chars.isChecked())
        self.inifile.set("General", "download sounds", self.allowdownload_sounds.isChecked())
        self.inifile.set("General", "download music", self.allowdownload_music.isChecked())
        self.inifile.set("General", "download evidence", self.allowdownload_evidence.isChecked())
        self.inifile.set("General", "theme", self.currtheme.currentText())
        self.inifile.set("General", "auto connect", self.autoconnect.currentIndex() - 1)
        self.inifile.set("General", "auto pick", self.autopick.currentText().toUtf8())
        self.inifile.set("General", "auto join area", self.autojoinarea.text().toUtf8())
        self.inifile.set("General", "install updates", self.check_updates.isChecked())

        self.inifile.set("Audio", "device", self.device_list.currentIndex())
        self.inifile.set("Audio", "Music volume", self.musicslider.value())
        self.inifile.set("Audio", "Sound volume", self.soundslider.value())
        self.inifile.set("Audio", "Blip volume", self.blipslider.value())

        with open("AO2XP.ini", "wb") as f:
            self.inifile.write(f)
        
        with open(AO2XPpath+"callwords.ini", "w") as f:
            f.write(self.callwords_edit.toPlainText().toUtf8())
            
        self.gamewindow.gamewidget.text_wait_time = self.textstaytime.value()
        self.gamewindow.gamewidget.slide_enabled = self.enableslide.isChecked()
        
        if not (self.savelogs_state == self.savetolog.isChecked() and self.combinelogs_state == self.savetolog_combine.isChecked()):
            self.gamewindow.gamewidget.ooclog.set_logfiles()
            self.gamewindow.gamewidget.icLog.set_logfiles(self.gamewindow.gamewidget.ooclog.logfile)
        
        if not self.savedemos_state == self.savedemos.isChecked():
            if self.savedemos.isChecked():
                self.gamewindow.gamewidget.start_demo_recorder()
            else:
                self.gamewindow.gamewidget.demo_recorder = None
        
        self.hide()
    
    def onCancelClicked(self):
        self.hide()
        
    def onAboutClicked(self):
        self.gamewindow.aboutgui.exec_()

    def onUpdateClicked(self):
        import updater
        code = updater.checkForUpdates()
        if code == 0:
            subprocess.Popen(["./AO2XPupdat"])
            _exit(0)
        elif osname == "Darwin": # bundle
            os.chdir(Cocoa.NSBundle.mainBundle().resourcePath()) # return to Resources folder

    def onReloadAudio(self):
        audio.free()
        audio.init()
        print "[audio] Reloaded audio system"