#!/usr/bin/env python2

import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

import os, sys
os.environ['GTK_THEME'] = 'light'

from gi.repository import GObject, Gst, Gtk, Gdk, GtkSource

GObject.threads_init()
Gdk.threads_init()

import command, validate, dialog

class SourceView(Gtk.Window):
    def __init__(self, filename=None):
        super(SourceView, self).__init__()

        self.filename = 'unsaved'

        self.connect("destroy", self.quit)
        self.set_default_size(1024, 768)
        self.set_border_width(10)
        self.set_title('Homeostasis editor')

        tabs = Gtk.Notebook()
        self.tabs = tabs

        vbox = Gtk.VBox() # contains tabs and buttons

        self.source_buffer = GtkSource.Buffer()
        lang_manager = GtkSource.LanguageManager()
        self.source_buffer.set_language(lang_manager.get_language('xml'))
        self.source_buffer.set_modified(False)
        self.source_view = GtkSource.View.new_with_buffer(self.source_buffer)
        self.source_view.set_show_line_numbers(True)
        self.source_view.set_tab_width(4)
        self.source_view.set_wrap_mode(Gtk.WrapMode.WORD)
        self.scrolled = Gtk.ScrolledWindow()
        self.scrolled.add(self.source_view)
        #vbox.pack_start(self.scrolled, True, True, 5)

        self.command = command.Command()
        #vbox.pack_start(self.command, False, True, 5)

        hbox = Gtk.HBox()
        new_button = Gtk.Button('New')
        new_button.connect('clicked', self.new)
        hbox.pack_start(new_button, False, False, 5)

        load_button = Gtk.Button('Load')
        load_button.connect('clicked', lambda *args: self.show_filechooser("load"))
        hbox.pack_start(load_button, False, False, 5)

        validate_button = Gtk.Button('Validate')
        validate_button.connect('clicked', self.validate)
        hbox.pack_start(validate_button, False, False, 5)

        compile_button = Gtk.Button('Compile')
        compile_button.connect('clicked', self.compile)
        hbox.pack_start(compile_button, False, False, 5)

        save_button = Gtk.Button('Save')
        save_button.connect('clicked', self.save)
        hbox.pack_start(save_button, False, False, 5)

        saveas_button = Gtk.Button('Save as')
        saveas_button.connect('clicked', lambda *args: self.show_filechooser("saveas"))
        hbox.pack_start(saveas_button, False, False, 5)

        vbox.pack_start(tabs, True, True, 5)
        vbox.pack_start(hbox, False, True, 5)

        tabs.append_page(self.scrolled, Gtk.Label(self.filename))
        tabs.append_page(self.command, Gtk.Label('Compilation result'))
        tabs.set_show_border(False)

        if filename != None:
            self.set_filename(filename)
            self.load()

        self.add(vbox)
        self.show_all()

        self.command.add_text('READY')

    def new(self, *args):
        if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename):
            self.source_buffer.set_text("""<homeostasis version="25-11-2014">
    <liste_section sequences="1" ordre="variable" repetition="oui" action="exclusive">
        <section id="2" action="example1">
            <sequence ordre="strict" repetition="non" action="" lang="esp">
                <keyword action="example2" lang="eng"> hello </keyword>
            </sequence>
        </section>
    </liste_section>
</homeostasis>""")
            self.set_filename('unsaved')

    def set_filename(self, filename):
        self.filename = filename
        self.tabs.set_tab_label(self.scrolled, Gtk.Label(os.path.basename(filename)))

    def show_filechooser(self, dialog_type="load"):
        if dialog_type == "load":
            chooser = Gtk.FileChooserDialog("Please choose a file to load", self, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
        else:
            chooser = Gtk.FileChooserDialog("Please set a file to save", self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
        filter_text = Gtk.FileFilter()
        filter_text.set_name("XML files")
        filter_text.add_mime_type("text/xml")
        chooser.add_filter(filter_text)
        chooser.set_current_folder('%s/data' % (os.path.dirname(__file__) or '.'))

        response = chooser.run()
        if response == -5:
            self.filename = chooser.get_filename()
            print self.filename
            self.set_filename(self.filename)
            chooser.destroy()
            if dialog_type == "load":
                return self.load()
            else:
                self.source_buffer.set_modified(True) # force to save
                return self.save()
        chooser.destroy()

    def load(self, *args):
        if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename):
            try:
                with open(self.filename) as fp:
                    self.source_buffer.set_text(fp.read())
                self.source_buffer.set_modified(False)
            except Exception as e:
                print e
                self.command.add_text('FAILED to load "%s"' % self.filename)
                return False
            return True
        return False

    def save(self, *args):
        if not self.source_buffer.get_modified(): # no need to save
            return True
        if os.path.exists(self.filename) and not dialog.confirm('Overwrite "%s"?' % self.filename):
            return False
        if self.filename == 'unsaved':
            return self.show_filechooser("save")
        else:
            self.command.clear()
            try:
                with open(self.filename, 'w') as fp:
                    bounds = self.source_buffer.get_bounds()
                    fp.write(self.source_buffer.get_text(bounds[0], bounds[1], True))
                self.source_buffer.set_modified(False)
            except Exception as e:
                print e
                self.command.add_text('FAILED to save as "%s"' % self.filename)
                return False
        return True

    def validate(self, *args):
        #self.command.clear()
        if self.save():
            self.command.add_text('VALIDATE...')
            self.tabs.set_current_page(1)
            result, message = validate.validate_xml(self.filename)
            self.command.add_text(message)
            if result:
                self.command.add_text('SUCCESS')
            else:
                self.command.add_text('FAILED')
            return result

    def compile(self, *args):
        #self.command.clear()
        self.tabs.set_current_page(1)
        if self.save():
            if self.validate():
                self.command.add_text('COMPILE...')
                self.command.run('./asr/tools/compile.sh "%s"' % self.filename)

    def quit(self, window):
        #if not self.source_buffer.get_modified() or dialog.confirm('Discard changes to "%s"?' % self.filename):
        Gtk.main_quit()
        #    return True
        #return False

if __name__ == '__main__':
    if len(sys.argv) > 1:
        app = SourceView(sys.argv[1])
    else:
        app = SourceView()
    Gtk.main()