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

    Copyright (C) 2007-2020 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/>.

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


#include <cmath>
#include <cairomm/context.h>

#include "../strings.hpp"
#include "../diary.hpp"
#include "calendar.hpp"


using namespace LIFEO;

// CHART ===========================================================================================
Calendar::Calendar()
{
    m_font_base.set_family( "Cantarell" );
    m_font_base.set_size( s_font_height * Pango::SCALE );

    m_font_bold.set_family( "Cantarell" );
    m_font_bold.set_weight( Pango::WEIGHT_BOLD );
    m_font_bold.set_size( s_font_height * Pango::SCALE );

    m_font_big.set_family( "Cantarell" );
    m_font_big.set_weight( Pango::WEIGHT_BOLD );
    m_font_big.set_size( 1.3 * s_font_height * Pango::SCALE );

    m_IS_entry_icon = Cairo::ImageSurface::create( Cairo::FORMAT_ARGB32, 16, 16 );
    m_IS_entry_icon_plus = Cairo::ImageSurface::create( Cairo::FORMAT_ARGB32, 16, 16 );
    m_IC_entry_icon = Cairo::Context::create( m_IS_entry_icon );
    m_IC_entry_icon_plus = Cairo::Context::create( m_IS_entry_icon_plus );
}

void
Calendar::init_icons()
{
    if( !m_flag_icons_initialized )
    {
        Gdk::Cairo::set_source_pixbuf( m_IC_entry_icon,
                                       Gtk::IconTheme::get_default()->load_icon( "entry-16", 16 ),
                                       0.0, 0.0 );
        m_IC_entry_icon->paint();

        Gdk::Cairo::set_source_pixbuf( m_IC_entry_icon_plus,
                                       Gtk::IconTheme::get_default()->load_icon( "entry_plus-16",
                                                                                 16 ),
                                       0.0, 0.0 );
        m_IC_entry_icon_plus->paint();

        m_flag_icons_initialized = true;
    }
}

void
Calendar::set_date( date_t date )
{
    if( Date::is_ordinal( date ) )
        return;

    m_month.m_date = Date::get_pure( date );
    if( m_month.is_set() )
        m_month.set_day( 1 );

    update();
}

void
Calendar::calculate_begin_date( date_t& begin_date )
{
    Date::set_day( begin_date, 1 );
    const auto days_before{ Date::get_weekday( begin_date ) };
    if( days_before > 0 )
    {
        Date::backward_months( begin_date, 1 ); // sets to last day of the month
        Date::set_day( begin_date, Date::get_day( begin_date ) - days_before + 1 );
    }
}

void
Calendar::update_col_geom( bool flag_new )
{
    m_col_width = ( m_width - ( 2 * s_margin ) ) / 7;
    m_row_height = ( m_height - s_margin - s_grid_start_y ) / 6;
}

void
Calendar::resize( int w, int h )
{
    bool flag_first( m_width < 0 );

    m_width = w;
    m_height = h;

    m_x_max = m_width - s_margin;
    m_length = m_x_max - s_margin;
    m_y_max = m_height - s_margin;

    update_col_geom( flag_first );
}

bool
Calendar::draw( const Cairo::RefPtr< Cairo::Context >& cr )
{
    // BACKGROUND
    cr->rectangle( 0.0, 0.0, m_width, m_height );
    cr->set_source_rgb( 1.0, 1.0, 1.0 );
    cr->fill();

    // HANDLE DATE NOT SET-CASE SPECIALLY
    if( ! m_month.is_set() )
    {
        cr->set_source_rgb( 0.0, 0.0, 0.0 );
        auto layout = Pango::Layout::create( cr );
        layout->set_text( _( "DATE IS NOT SET" ) );
        layout->set_font_description( m_font_big );
        int w, h;
        layout->get_pixel_size( w, h );
        cr->move_to( ( m_width - w ) / 2 , m_height / 2 );
        layout->show_in_cairo_context( cr );

        return true;
    }

    // TITLE
    cr->set_source_rgb( 0.2, 0.1, 0.1 );
    auto layout_title = Pango::Layout::create( cr );
    layout_title->set_text( STR::compose( m_month.get_month_str(), "   ", m_month.get_year() ) );
    layout_title->set_font_description( m_font_big );
    int w, h;
    layout_title->get_pixel_size( w, h );
    cr->move_to( ( m_width - w ) / 2, s_margin );
    layout_title->show_in_cairo_context( cr );

    // GRID
//    cr->set_line_width( 0.5 );
//    cr->set_source_rgb( 0.5, 0.5, 0.5 );

//    for( int i = 0; i <= 7; i++ )
//    {
//        cr->move_to( s_margin + m_col_width * i, s_grid_start_y );
//        cr->line_to( s_margin + m_col_width * i, m_y_max );
//    }
//
//    for( int i = 0; i <= 6; i++ )
//    {
//        cr->move_to( s_margin, s_grid_start_y + m_row_height * i );
//        cr->line_to( m_x_max, s_grid_start_y + m_row_height * i );
//    }

    cr->stroke();

    // DAY NUMBERS & OTHER CELL CONTENT
    auto&& layout{ Pango::Layout::create( cr ) };
    Date date{ m_month.m_date };
    const auto days_before = date.get_weekday();
    date.backward_months( 1 );
    date.set_day( date.get_days_in_month() - days_before );
    const auto today = Date::get_today();

    layout->set_font_description( m_font_big );
    layout->set_text( "1" );
    layout->get_pixel_size( w, h ); // store height

    for( int j = 0; j < 6; j++ )
    {
        for( int i = 0; i < 7; i++ )
        {
            date.forward_days( 1 );

            // HOVER AND CHAPTER BG COLOR
            auto chapter{ Diary::d->get_chapter_ctg_cur()->get_chapter_around( date.m_date ) };

            if( chapter || date.m_date == m_day_selected || date.m_date == today )
            {
                cr->move_to( s_margin + i * m_col_width + 0.5,
                             s_grid_start_y + j * m_row_height + 0.5 );
                cr->rel_line_to( m_col_width - 1, 0 );
                cr->rel_line_to( 0, m_row_height - 1 );
                cr->rel_line_to( -m_col_width + 1, 0 );
                cr->close_path();

                if( date.m_date == m_day_selected )
                {
                    cr->set_source_rgb( 1.0, 0.92, 0.92 );
                    cr->fill_preserve();
                }
                else if( chapter )
                {
                    Gdk::Cairo::set_source_rgba(
                            cr, midtone( chapter->get_color(), Color( "#FFFFFF" ), 0.8 ) );
                    cr->fill_preserve();
                }

                if( date.m_date == today )
                {
                    cr->set_source_rgb( 0.5, 0.3, 0.3 );
                    cr->set_line_width( 1.5 );
                    cr->stroke();
                }
                else
                    cr->begin_new_path(); // clears the path
            }

            // DAY NUMBER
            if( date.get_month() == m_month.get_month() )
                cr->set_source_rgb( 0.5, 0.3, 0.3 );
            else
                cr->set_source_rgb( 0.8, 0.7, 0.7 );
            layout->set_text( STR::compose( date.get_day() ) );
            cr->move_to( s_margin + i * m_col_width + s_border_label,
                         s_grid_start_y + ( j + 0.5 ) * m_row_height - h / 2 );
            layout->show_in_cairo_context( cr );

            // ENTRY ICON
            auto entry_count{ Diary::d->get_entry_count_on_day( date ) };
            if( entry_count > 0 )
            {
                if( !m_flag_icons_initialized )
                    init_icons();

                if( date.m_date == m_day_shown )
                {
                    cr->set_line_width( 1.5 );
                    cr->begin_new_path();
                    cr->arc( s_margin + ( i + 0.4 ) * m_col_width + 8,
                            s_grid_start_y + ( j + 0.5 ) * m_row_height,
                            12.0, 0.0, 2 * HELPERS::PI );
                    cr->stroke();
                }
                cr->set_source( entry_count > 1 ? m_IS_entry_icon_plus : m_IS_entry_icon,
                                s_margin + ( i + 0.4 ) * m_col_width,
                                s_grid_start_y + ( j + 0.5 ) * m_row_height - 8 );
                cr->rectangle( s_margin + ( i + 0.4 ) * m_col_width,
                               s_grid_start_y + ( j + 0.5 ) * m_row_height - 8,
                               16, 16 );
                cr->clip();
                cr->paint();
                cr->reset_clip();
            }
        }
    }

    // DAY NAMES
    layout->set_font_description( m_font_bold );
    layout->set_width( ( m_col_width - 5 ) * Pango::SCALE );
    layout->set_ellipsize( Pango::ELLIPSIZE_END );
    Date date_day{ 2019, 12, 22 }; // this is a Sunday
    for( int i = 0; i < 7; i++ )
    {
        cr->set_source_rgb( 0.5, 0.4, 0.4 );
        layout->set_text( date_day.get_weekday_str() );
        cr->move_to( //s_margin + ( i + 0.5 ) * m_col_width - ( w / 2 ),
                     s_margin + i * m_col_width + s_border_label,
                     s_margin + s_title_bar_height );
        layout->show_in_cairo_context( cr );

        date_day.forward_days( 1 );
    }

    return true;
}
