/***********************************************************************************

    Copyright (C) 2007-2018 Ahmet Öztürk (aoz_2@yahoo.com)

    This file is part of Lifeograph.

    Lifeograph 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 3 of the License, or
    (at your option) any later version.

    Lifeograph 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 Lifeograph.  If not, see <http://www.gnu.org/licenses/>.

***********************************************************************************/


#ifndef LIFEOGRAPH_VIEWS_HEADER
#define LIFEOGRAPH_VIEWS_HEADER


#include "strings.hpp"
#include "diarydata.hpp"
#include "entry.hpp"
#include "widget_chart.hpp"
#include "dialog_export.hpp"
#include "dialog_password.hpp"
#include "widget_textview.hpp"


namespace LIFEO
{

template< class T >
class ElementViewWithChart : public ElementView< T >
{
    public:
        ElementViewWithChart( const Ustring );
        //{ initialize(); }
        //virtual ~ElementViewWithChart() { }

        bool handle_zoom( Gtk::ScrollType, double );
        void handle_type_changed();
        void update_points( bool = true );
        void handle_chart_shown();
        void handle_chart_underlay();

    protected:
        WidgetChart*            m_widgetchart;
        Gtk::Scale*             m_Sc_chart;
        Gtk::MenuButton*        m_MB_chart;
        Gtk::Popover*           m_Po_chart;
        Gtk::RadioButton*       m_RB_chart_monthly;
        Gtk::RadioButton*       m_RB_chart_yearly;
        Gtk::ModelButton*       m_B_underlay;
        Glib::RefPtr< Gio::SimpleAction >
                                m_A_underlay;

    private:
        //void                    initialize();

};

// TAG VIEW ========================================================================================
class TagView : public ElementViewWithChart< Tag >
{
    public:
                                TagView();

        Glib::ustring           get_title_str() const
        { return m_ptr2elem->get_name(); }
        Glib::ustring           get_info_str() const;

        Gtk::Popover*           get_popover() override;

        void                    handle_login();
        void                    show( Tag& tag );

        void                    update_combobox_categories();

        enum TagComboType { TCT_NONE, TCT_CATEGORY, TCT_NEW, TCT_SEPARATOR };

    protected:
        bool                    is_title_editable() const
        { return( m_ptr2elem->get_type() == DiaryElement::ET_TAG ); }
        Glib::ustring           get_title_edit_str() const
        { return m_ptr2elem->get_name(); }
        bool                    check_title_applicable( const Glib::ustring& ) const;
        bool                    apply_title( const Glib::ustring& );

        void                    handle_filter_toggled();
        void                    handle_category_changed();
        void                    handle_type_changed();
        void                    handle_unit_changed();

        bool                    is_row_separator( const Glib::RefPtr< Gtk::TreeModel >&,
                                                  const Gtk::TreeIter );

        void                    handle_theme_motion_notify_event( GdkEventMotion* );
        void                    handle_theme_button_release_event( GdkEventButton* );
        void                    add_action_theme_text( const Glib::ustring&,
                                                       const Glib::RefPtr< Gtk::TextTag >& );
        void                    add_tagged_theme_text( const Glib::ustring&,
                                                       const Glib::RefPtr< Gtk::TextTag >& );
        void                    add_plain_theme_text( const Glib::ustring& );
        void                    launch_color_dialog( Gdk::RGBA& );
        void                    launch_font_dialog();

        void                    update_theme_view();
        void                    update_theme_menu();
        void                    reset_theme();
        void                    copy_theme_from( const Tag* );

        bool                    handle_chart_zoom( Gtk::ScrollType, double );
        bool                    handle_chart_type();

        void                    dismiss_tag();

        Gtk::Grid*              m_G_general;
        Gtk::Grid*              m_G_theme;
        Gtk::ModelButton*       m_B_dismiss;
        Gtk::ComboBox*          m_CB_category;
        Gtk::ComboBoxText*      m_CB_type;
        Gtk::ComboBoxText*      m_CB_unit;
        Gtk::Entry*             m_E_unit;

        Gtk::TextView*          m_textview_theme;
        Gtk::MenuButton*        m_MB_theme;
        Gtk::Popover*           m_Po_theme;
        Gtk::ModelButton*       m_B_themes;
        Gtk::ModelButton*       m_B_theme_reset;
        Gtk::Box*               m_Bx_themes;

        Gtk::ModelButton*       m_B_filtering;

        class ColrecCategory : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ColrecCategory() { add( name ); add( ptr ); add( type ); }
                Gtk::TreeModelColumn< Glib::ustring >       name;
                Gtk::TreeModelColumn< CategoryTags* >       ptr;
                Gtk::TreeModelColumn< TagComboType >        type;
        };

        Glib::RefPtr< Gtk::ListStore >
                                m_liststore_categories;
        ColrecCategory          colrec_category;

        Glib::RefPtr< Gtk::TextTag >     m_tag_action;
        Glib::RefPtr< Gtk::TextTag >     m_tag_heading;
        Glib::RefPtr< Gtk::TextTag >     m_tag_subheading;
        Glib::RefPtr< Gtk::TextTag >     m_tag_normal;
        Glib::RefPtr< Gtk::TextTag >     m_tag_match;
        Glib::RefPtr< Gtk::TextTag >     m_tag_highlight;
        Glib::RefPtr< Gtk::TextTag >     m_tag_comment;
        Glib::RefPtr< Gtk::TextTag >     m_tag_link;
        Glib::RefPtr< Gtk::TextTag >     m_tag_link_broken;
        Glib::RefPtr< Gtk::TextTag >     m_tag_font;
        Glib::RefPtr< Gtk::TextTag >     m_tag_background;
        Glib::RefPtr< Gtk::TextTag >     m_tag_region;
};

// TAG CATEGORY VIEW ===============================================================================
class CategoryTagsView : public ElementView< CategoryTags >
{
    public:
                                CategoryTagsView();

        Glib::ustring           get_title_str() const
        { return m_ptr2elem->m_name; }
        Glib::ustring           get_info_str() const
        { return Glib::ustring::compose( _( "Tag category with %1 tags" ),
                                         m_ptr2elem->size() ); }

        Gtk::Popover*           get_popover() override;

        void                    show( CategoryTags& );

    protected:
        bool                    is_title_editable() const
        { return true; }
        Glib::ustring           get_title_edit_str() const
        { return m_ptr2elem->get_name(); }
        bool                    check_title_applicable( const Glib::ustring& ) const;
        bool                    apply_title( const Glib::ustring& );

        void                    dismiss_category();

        Gtk::ModelButton*       m_B_dismiss;
};

// CHAPTER VIEW ====================================================================================
class ChapterView : public ElementViewWithChart< Chapter >
{
    public:
                                ChapterView();

        Glib::ustring           get_title_str() const
        {
            Glib::ustring title;

            if( ! m_ptr2elem->get_date().is_hidden() )
            {
                title = m_ptr2elem->get_date().format_string();
                title += "  ";
            }

            title += m_ptr2elem->m_name;

            return title;
        }
        Glib::ustring           get_info_str() const
        {
            if( m_ptr2elem->m_time_span )
                return Glib::ustring::compose( _( "Dated Chapter with %1 entries in %2 days" ),
                                               m_ptr2elem->get_size(), m_ptr2elem->m_time_span );
            else
                return Glib::ustring::compose( _( STRING::ELEM_WITH_ENTRIES ),
                                               m_ptr2elem->get_type_name(),
                                               m_ptr2elem->get_size() );
        }

        Gtk::Popover*           get_popover() override;

        void                    handle_login();
        void                    show( Chapter& );

        void                    set_todo_status( ElemStatus status );

    protected:
        bool                    is_title_editable() const
        { return true; }
        Glib::ustring           get_title_edit_str() const
        { return m_ptr2elem->m_name; }
        bool                    check_title_applicable( const Glib::ustring& ) const;
        bool                    apply_title( const Glib::ustring& );

        void                    handle_date_changed();
        void                    handle_date_applied();
        void                    handle_color_changed();

        void                    update_labels();

        void                    add_new_entry();
        void                    dismiss_chapter();

        Gtk::Image*             m_I_not_todo;
        Gtk::RadioButton*       m_RB_not_todo;
        Gtk::RadioButton*       m_RB_todo;
        Gtk::RadioButton*       m_RB_progressed;
        Gtk::RadioButton*       m_RB_done;
        Gtk::RadioButton*       m_RB_canceled;
        Gtk::Button*            m_B_dismiss;

        Gtk::Entry*             m_E_begins;
        Gtk::Button*            m_B_date_apply;
        Gtk::Label*             m_L_ends;
        Gtk::ColorButton*       m_ClB_color;
        Gtk::Button*            m_B_new_entry;

        Gtk::Grid*              m_G_edit;
        Gtk::Grid*              m_G_actions;
        Gtk::Grid*              m_G_chart;
};

// FILTER VIEW =====================================================================================
// ATTENTION: FilterView is just a Gtk::Popover not an ElementView any more
class FilterView
{
    public:
                                FilterView();

        /*Glib::ustring           get_title_str() const
        { return m_ptr2elem->get_name(); }
        Glib::ustring           get_info_str() const;*/

        void                    handle_login();
        //void                    show( Filter& );

        void                    update();

    protected:
        bool                    is_title_editable() const
        { return( false ); }
        Glib::ustring           get_title_edit_str() const
        { return m_ptr2elem->get_name(); }
        bool                    check_title_applicable( const Glib::ustring& ) const
        { return false; }
        bool                    apply_title( const Glib::ustring& )
        { return false; }

        void                    make_default();

        void                    handle_trash_changed();
        void                    handle_favored_changed();
        void                    handle_todo_changed();

        void                    clear_tag();
        bool                    handle_tag_dropped(
                                        const Glib::RefPtr< Gdk::DragContext >&,
                                        int, int, guint );

        void                    handle_date_begin_changed();
        void                    handle_date_end_changed();

        void                    update_entries();
        void                    remove_selected_entries();
        void                    remove_all_entries();
        bool                    handle_entry_dropped(
                                        const Glib::RefPtr< Gdk::DragContext >&,
                                        int, int, guint );
        void                    handle_entry_selection_changed();

        Filter*                 m_ptr2elem;

        Gtk::ToggleButton*      m_TB_todo_not;
        Gtk::ToggleButton*      m_TB_todo_open;
        Gtk::ToggleButton*      m_TB_todo_progressed;
        Gtk::ToggleButton*      m_TB_todo_done;
        Gtk::ToggleButton*      m_TB_todo_canceled;
        Gtk::ToggleButton*      m_TB_not_favored;
        Gtk::ToggleButton*      m_TB_favored;
        Gtk::ToggleButton*      m_TB_not_trashed;
        Gtk::ToggleButton*      m_TB_trashed;

        Gtk::Label*             m_L_tag;
        Gtk::Button*            m_B_clear_tag;

        EntryClear*             m_E_date_begin;
        EntryClear*             m_E_date_end;

        Gtk::TreeView*          m_TV_entries;
        Glib::RefPtr< Gtk::ListStore >      m_LS_entries;
        Gtk::Button*            m_B_remove_entry;
        Gtk::Button*            m_B_rm_all_entries;

        Gtk::Button*            m_B_make_default;
        Gtk::Button*            m_B_revert;

        class ColrecEntries : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ColrecEntries()
                {
                    add( name );
                    add( ptr );
                }
                Gtk::TreeModelColumn< Glib::ustring > name;
                Gtk::TreeModelColumn< Entry* > ptr;
        };

        static ColrecEntries*   colrec_entries;

};

// DIARY VIEW ======================================================================================
class DiaryView : public ElementViewWithChart< Diary >
{
    public:
                                DiaryView();
                                ~DiaryView();

        Glib::ustring           get_list_str() const
        { return Glib::ustring::compose( "<b>%1</b>",
                Glib::Markup::escape_text(
                        Glib::filename_display_basename( m_ptr2elem->m_path ) ) ); }
        Glib::ustring           get_title_str() const
        { return m_ptr2elem->m_name; }
        Glib::ustring           get_info_str() const
        {
            // TRANSLATORS: %3 stands for "Encrypted diary" or "Unencrypted diary"
            return Glib::ustring::compose( _( "%3 with %1 entries spanning %2 days" ),
                                           m_ptr2elem->m_entries.size(),
                                           Diary::d->get_time_span(),
                                           Diary::d->is_encrypted() ?
                                                   _( "Encrypted diary" ) :
                                                   _( "Unencrypted diary" ) );
        }

        void                    handle_login();
        void                    show( Diary& );

        void                    update_startup_elem();

    protected:
        // DIALOGS
        void                    start_dialog_password();
        void                    start_dialog_import();
        void                    start_dialog_export();
        void                    open_diary_folder();
        void                    handle_language_changed();
        void                    handle_startup_type_changed();
        bool                    handle_startup_elem_drag_motion(
                                        const Glib::RefPtr< Gdk::DragContext >&,
                                        int, int, guint );
        bool                    handle_startup_elem_dropped(
                                        const Glib::RefPtr< Gdk::DragContext >&,
                                        int, int, guint );
        bool                    go_to_startup_elem( const Glib::ustring& );

        void                    update_combobox_chapter_ctg();
        void                    handle_cur_chapter_ctg_changed();
        void                    rename_cur_chapter_ctg();
        void                    dismiss_cur_chapter_ctg();
        bool                    is_row_separator( const Glib::RefPtr< Gtk::TreeModel >&,
                                                  const Gtk::TreeIter );

        Gtk::ModelButton*       m_B_import;
        Gtk::Separator*         m_S_encryption;
        Gtk::ModelButton*       m_B_encryption;

        Gtk::Frame*             m_frame_startup;
        Gtk::Frame*             m_frame_chapters;

        Gtk::Label*             m_L_path;
        Gtk::ComboBoxText*      m_CB_spellcheck;

        // STARTUP
        Gtk::ComboBox*          m_CB_startup_type;
        Gtk::Label*             m_L_startup_elem;
        Gtk::Label*             m_L_startup_elem_drop;

        class ColrecStartupType : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ColrecStartupType() { add( name ); add( type ); }
                Gtk::TreeModelColumn< Glib::ustring >   name;
                Gtk::TreeModelColumn< DEID >            type;
        };

        Glib::RefPtr< Gtk::ListStore >
                                m_liststore_startup_type;
        ColrecStartupType       colrec_startup_type;

        // CHAPTER CATEGORIES & TOPICS
        Gtk::ComboBox*          m_CB_chapter_ctg;
        Gtk::Button*            m_B_chapter_ctg_dismiss;
        Gtk::Button*            m_B_chapter_ctg_rename;

        enum ChapterCtgComboType { CCCT_CATEGORY, CCCT_NEW, CCCT_SEPARATOR };

        class ColrecChapterCtg : public Gtk::TreeModel::ColumnRecord
        {
            public:
                ColrecChapterCtg() { add( name ); add( ptr ); add( type ); }
                Gtk::TreeModelColumn< Glib::ustring >       name;
                Gtk::TreeModelColumn< CategoryChapters* >   ptr;
                Gtk::TreeModelColumn< ChapterCtgComboType > type;
        };

        Glib::RefPtr< Gtk::ListStore >
                                m_liststore_chapter_ctg;
        ColrecChapterCtg        colrec_chapter_ctg;

        // DIALOGS
        DialogImport*           m_dialog_import{ nullptr };
        DialogExport*           m_dialog_export{ nullptr };
};

} // end of namespace LIFEO

#endif

