"""
Copyright 2008, 2009, 2011 Free Software Foundation, Inc.
This file is part of GNU Radio

GNU Radio Companion 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.

GNU Radio Companion 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
"""

import pygtk
pygtk.require('2.0')
import gtk
import gobject
import Actions
from StateCache import StateCache
from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT
from DrawingArea import DrawingArea
import os


class NotebookPage(gtk.HBox):
    """A page in the notebook."""

    def __init__(self, main_window, flow_graph, file_path=''):
        """
        Page constructor.

        Args:
            main_window: main window
            file_path: path to a flow graph file
        """
        self._flow_graph = flow_graph
        self.process = None
        #import the file
        self.main_window = main_window
        self.file_path = file_path
        initial_state = flow_graph.get_parent().parse_flow_graph(file_path)
        self.state_cache = StateCache(initial_state)
        self.saved = True
        #import the data to the flow graph
        self.get_flow_graph().import_data(initial_state)
        #initialize page gui
        gtk.HBox.__init__(self, False, 0)
        self.show()
        #tab box to hold label and close button
        self.tab = gtk.HBox(False, 0)
        #setup tab label
        self.label = gtk.Label()
        self.tab.pack_start(self.label, False)
        #setup button image
        image = gtk.Image()
        image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU)
        #setup image box
        image_box = gtk.HBox(False, 0)
        image_box.pack_start(image, True, False, 0)
        #setup the button
        button = gtk.Button()
        button.connect("clicked", self._handle_button)
        button.set_relief(gtk.RELIEF_NONE)
        button.add(image_box)
        #button size
        w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU)
        button.set_size_request(w+6, h+6)
        self.tab.pack_start(button, False)
        self.tab.show_all()
        #setup scroll window and drawing area
        self.scrolled_window = gtk.ScrolledWindow()
        self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.scrolled_window.connect('key-press-event', self._handle_scroll_window_key_press)
        self.drawing_area = DrawingArea(self.get_flow_graph())
        self.scrolled_window.add_with_viewport(self.get_drawing_area())
        self.pack_start(self.scrolled_window)
        #inject drawing area into flow graph
        self.get_flow_graph().drawing_area = self.get_drawing_area()
        self.show_all()

    def get_drawing_area(self): return self.drawing_area

    def _handle_scroll_window_key_press(self, widget, event):
        """forward Ctrl-PgUp/Down to NotebookPage (switch fg instead of horiz. scroll"""
        is_ctrl_pg = (
            event.state & gtk.gdk.CONTROL_MASK and
            event.keyval in (gtk.keysyms.Page_Up, gtk.keysyms.Page_Down)
        )
        if is_ctrl_pg:
            return self.get_parent().event(event)

    def get_generator(self):
        """
        Get the generator object for this flow graph.

        Returns:
            generator
        """
        platform = self.get_flow_graph().get_parent()
        return platform.Generator(self.get_flow_graph(), self.get_file_path())

    def _handle_button(self, button):
        """
        The button was clicked.
        Make the current page selected, then close.

        Args:
            the: button
        """
        self.main_window.page_to_be_closed = self
        Actions.FLOW_GRAPH_CLOSE()

    def set_markup(self, markup):
        """
        Set the markup in this label.

        Args:
            markup: the new markup text
        """
        self.label.set_markup(markup)

    def get_tab(self):
        """
        Get the gtk widget for this page's tab.

        Returns:
            gtk widget
        """
        return self.tab

    def get_proc(self):
        """
        Get the subprocess for the flow graph.

        Returns:
            the subprocess object
        """
        return self.process

    def set_proc(self, process):
        """
        Set the subprocess object.

        Args:
            process: the new subprocess
        """
        self.process = process

    def term_proc(self):
        """
        Terminate the subprocess object

        Add a callback to kill the process
        after 2 seconds if not already terminated
        """
        def kill(process):
            """
            Kill process if not already terminated

            Called by gobject.timeout_add

            Returns:
                False to stop timeout_add periodic calls
            """
            is_terminated = process.poll()
            if is_terminated is None:
                process.kill()
            return False

        self.get_proc().terminate()
        gobject.timeout_add(2000, kill, self.get_proc())

    def get_flow_graph(self):
        """
        Get the flow graph.

        Returns:
            the flow graph
        """
        return self._flow_graph

    def get_read_only(self):
        """
        Get the read-only state of the file.
        Always false for empty path.

        Returns:
            true for read-only
        """
        if not self.get_file_path(): return False
        return os.path.exists(self.get_file_path()) and \
        not os.access(self.get_file_path(), os.W_OK)

    def get_file_path(self):
        """
        Get the file path for the flow graph.

        Returns:
            the file path or ''
        """
        return self.file_path

    def set_file_path(self, file_path=''):
        """
        Set the file path, '' for no file path.

        Args:
            file_path: file path string
        """
        self.file_path = os.path.abspath(file_path) if file_path else ''

    def get_saved(self):
        """
        Get the saved status for the flow graph.

        Returns:
            true if saved
        """
        return self.saved

    def set_saved(self, saved=True):
        """
        Set the saved status.

        Args:
            saved: boolean status
        """
        self.saved = saved

    def get_state_cache(self):
        """
        Get the state cache for the flow graph.

        Returns:
            the state cache
        """
        return self.state_cache