/*
 * File Name: test_main_window.h
 */

/*
 * This file is part of uds-plugin-pdf.
 *
 * uds-plugin-pdf 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.
 *
 * uds-plugin-pdf 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, see <http://www.gnu.org/licenses/>.
 */

/**
 * Copyright (C) 2008 iRex Technologies B.V.
 * All rights reserved.
 */

#ifndef TEST_MAIN_WINDOW_H_
#define TEST_MAIN_WINDOW_H_

#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf-core.h>
#include "test_gtk_source.h"
#include "test_output_device.h"
#include "pdf_doc_controller.h"
#include "pdf_page.h"
#include "pdf_collection.h"
#include "pdf_searcher.h"

namespace test
{

using namespace pdf;

struct BoundingRectangles
{
    std::vector<GdkRectangle*> rects;

    BoundingRectangles(): rects() {}
    ~BoundingRectangles() 
    {
        release();
    }

    void release()
    {
       typedef std::vector<GdkRectangle*>::iterator Iter;
       for(Iter i = rects.begin(); i != rects.end(); ++i)
       {
           delete *i;
       }
       rects.clear();
    }
};

/// @brief The main window of the UDS. It's the parent window of 
/// all ViewCtrls' windows.
class MainWindow
{
public:
    MainWindow();
    ~MainWindow();

    /// @brief Retrieve Gtk widget directly. It serves as parent widget for all 
    /// sub views.
    inline GtkWidget *get_main_window() { return main_window; }

private:
    /// @brief Create the main widget. The main widget will be 
    /// used as container for all ViewCtrl and the sub views.
    void create();

    /// @brief Destory the main widget and related resouce.
    void destory();

    /// @brief Enable main window to handle events.
    void connect_event_handlers(GtkWidget *widget);

    void update_window();

    void update_output_device();

    /// @brief Handler of rendering page
    void handle_page_ready(PagePtr cur_page, unsigned int ref_id);

    /// @brief Handler of searching ready
    void handle_searching_done(SearchResult ret, PDFSearchCollection* results
        , unsigned int ref_id);

    /// @brief Expose event handler.
    gboolean on_expose(GtkWidget *widget, GdkEvent *event);

    /// @brief Configure event handler, such as resize
    gboolean on_configure(GtkWidget *widget, GdkEvent *event);

    /// @brief Button press event handler.
    gboolean on_button_press(GtkWidget *widget, GdkEvent *event);

    /// @brief Button release event handler.
    gboolean on_button_release(GtkWidget *widget, GdkEvent *event);

    /// @brief Button move event handler.
    gboolean on_motion_notify(GtkWidget *widget, GdkEvent *event);

    /// @brief Key press event handler.
    gboolean on_key_press(GtkWidget *widget, GdkEvent *event);

    /// @brief Key release event handler.
    gboolean on_key_release(GtkWidget *widget, GdkEvent *event);

    /// @brief Widget delete event handler.
    gboolean on_delete(GtkWidget *widget, GdkEvent *event);

    //Test function 
private:
    void open_document(const std::string &filename);

    void search_next(bool forward = true);

    void search_all();

    void draw();

    void draw_page_bitmap(const PagePtr page);

    void draw_search_results();

private:
    struct TestBitmap
    {
        int width;
        int height;
        int row_stride;
        unsigned char *data;

        TestBitmap() : width(0), height(0), row_stride(0), data(0) {}
        ~TestBitmap() {}
    };

    typedef PDFCollection<PDFSearchDocument*> PDFSearchDocuments;

    struct SearchResultsContext
    {
        //The data of the search results
        PDFSearchCollection *data;

        //The bounding rectangles
        BoundingRectangles rects;

        //Flag indicating the searching status
        bool b_searching;

        //Flag indicating whether display the searching results
        bool b_display;

        //Anchor of current search result
        //ONLY for search next
        std::string cur_pos;

        //Current reference id
        unsigned int ref_id;

        //Forward?
        bool b_forward;

        SearchResultsContext() 
            : rects()
            , b_searching(false)
            , b_display(true)
            , cur_pos() 
            , ref_id(-1)
            , b_forward(false) {}
        ~SearchResultsContext() {}
    };

private:
    //The GTK window.
    GtkWidget *main_window;

    //The event source which receives all of the gtk event.
    typedef gtk::GtkEventSource<MainWindow> EventSource;
    EventSource source;

    // The graphics context.
    GdkGC *gc;

    // The buffering pixmap.
    GdkDrawable *pixmap;

    // The output device
    OutputDevice output_dev;

    // PDF Document
    PDFController document;

    // Number of current page
    int current_page;

    // Page data of current page
    PagePtr current_page_data;

    // The set of search results
    SearchResultsContext search_results;

};

}; //namespace test

#endif

