//  BMP
//  Copyright (C) 2005-2007 BMP development.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License Version 2
//  as published by the Free Software Foundation.
//
//  This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//  --
//
//  The BMPx project hereby grants permission for non-GPL compatible GStreamer
//  plugins to be used and distributed together with GStreamer and BMPx. This
//  permission is above and beyond the permissions granted by the GPL license
//  BMPx is covered by.

#include <iostream>
#include <gtkmm.h>

#include <cairomm/cairomm.h>

#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>

#include "button.hh"

#include "src/paths.hh"
#include "src/ui-tools.hh"

namespace Bmp
{
    SourceButton::SourceButton () : Gtk::Button (),
                                    m_label     (0),
                                    m_image     (Glib::RefPtr<Gdk::Pixbuf>(0)),
                                    m_pressed   (false),
                                    m_inside    (false),
                                    m_active    (false),
                                    m_playing   (false)
    {
      GError * error = 0;

      std::string filename;
      std::string svgdata;

      filename = BMP_IMAGE_DIR_SVG G_DIR_SEPARATOR_S "button-background.svg";
      svgdata  = Glib::file_get_contents (filename);
      _handle_background = rsvg_handle_new ();
      rsvg_handle_write (_handle_background, reinterpret_cast<unsigned char const*> (svgdata.c_str ()), svgdata.size (), &error);
      rsvg_handle_close (_handle_background, &error);

      filename = BMP_IMAGE_DIR_SVG G_DIR_SEPARATOR_S "button-outline.svg";
      svgdata  = Glib::file_get_contents (filename);
      _handle_outline = rsvg_handle_new ();
      rsvg_handle_write (_handle_outline, reinterpret_cast<unsigned char const*> (svgdata.c_str ()), svgdata.size (), &error);
      rsvg_handle_close (_handle_outline, &error);
    }

    SourceButton::~SourceButton ()
    {
      rsvg_handle_free (_handle_background);
      if (m_label)
        delete m_label;
    }

    void
    SourceButton::set_active (bool active)
    {
      m_active = active;
      queue_draw ();
    }

    void
    SourceButton::set_playing (bool playing)
    {
      m_playing = playing;
      queue_draw ();
    }

    bool
    SourceButton::get_active ()
    {
      return m_active;
    }

    bool
    SourceButton::get_playing ()
    {
      return m_playing;
    }

    void
    SourceButton::set_image (Glib::RefPtr<Gdk::Pixbuf> const& image)
    {
      m_image = image;
      queue_draw ();
    }

    void
    SourceButton::clear_image ()
    {
      m_image.clear();
      queue_draw ();
    }

    void
    SourceButton::set_label (Glib::ustring const& text, bool mnemonic)
    {
      create_label (text, mnemonic);
      queue_draw ();
    }

    void
    SourceButton::clear_label ()
    {
      if (m_label)
        {
          delete m_label;
        }

      //FIXME: Do we need to re-request size ?

      queue_draw ();
    }

    void
    SourceButton::on_size_request
                                    (Gtk::Requisition * req)
    {
      req->height = 0;
      req->width  = 0;

      if (m_image)
      {
        req->height += m_image->get_height() + 8;
        req->width   = m_image->get_width() + 20;
      }

      if (m_label)
      {
        Pango::Rectangle r = m_label->get_layout()->get_pixel_ink_extents();
        req->height += r.get_height() + 16;
        req->width   = (r.get_width() > m_image->get_width()) ? (r.get_width() + 20) : req->width;
      }
    }

    void
    SourceButton::on_enter ()
    {
      m_inside = true;
    }

    void
    SourceButton::on_leave ()
    {
      m_inside = false;
    }

    void
    SourceButton::on_pressed ()
    {
      if (!has_focus ())
        grab_focus ();

      m_pressed = true;
    }

    void
    SourceButton::on_released ()
    {
      if (m_inside)
        clicked ();
      m_pressed = false;
    }

    void
    SourceButton::on_activate ()
    {
      clicked ();
    }

    bool
    SourceButton::on_expose_event (GdkEventExpose * event)
    {
      int xoff = get_allocation().get_x();
      int yoff = get_allocation().get_y();

      double w = get_allocation().get_width();
      double h = get_allocation().get_height();

      Cairo::RefPtr<Cairo::Context> cr = get_window ()->create_cairo_context ();

      if (get_playing())
      {
        cr->save ();
        cr->set_operator (Cairo::OPERATOR_SOURCE);
        cr->translate (xoff, yoff);
        cr->scale (w / 128., h / 128.);
        rsvg_handle_render_cairo (_handle_background, cr->cobj());
        cr->restore ();
      }
      else if (get_active())
      {
        cr->save ();
        cr->set_operator (Cairo::OPERATOR_SOURCE);
        cr->translate (xoff, yoff);
        cr->scale (w / 128., h / 128.);
        rsvg_handle_render_cairo (_handle_outline, cr->cobj());
        cr->restore ();
      }

      if (m_image)
      {
        int x = (get_allocation().get_width() - m_image->get_width())/2 + xoff;
        int y = (get_allocation().get_height() - m_image->get_height())/2 - 8 + yoff;
        get_window ()->draw_pixbuf (Glib::RefPtr<Gdk::GC> (0),
                                    m_image,
                                    0, 0,
                                    x + ((m_pressed&&m_inside)? 1:0),
                                    y + ((m_pressed&&m_inside)? 1:0),
                                    -1, -1,
                                    Gdk::RGB_DITHER_MAX, 0, 0);
      }

      if (m_label)
      {
        Pango::Rectangle r = m_label->get_layout()->get_pixel_ink_extents();
        int x = (get_allocation().get_width() - r.get_width())/2;
        int y = (get_allocation().get_height() - r.get_height() - 10);

        cr->move_to (xoff + x + ((m_pressed&&m_inside)? 1:0),
                     yoff + y + ((m_pressed&&m_inside)? 1:0));

        if (get_playing())
        {
          cr->set_source_rgba (1., 1., 1., 1.);
        }
        else
        if (get_active())
        {
          cr->set_source_rgba (0.4, 0.4, 0.4, 1.);
        }
        else
        {
          Gdk::Color c (get_style()->get_fg (Gtk::STATE_NORMAL));
          cr->set_source_rgba (c.get_red_p(), c.get_green_p(), c.get_blue_p(), 1.);
        }

        pango_cairo_show_layout (cr->cobj(), m_label->get_layout()->gobj());
      }

      if (has_focus())
      {
        Gdk::Rectangle allocation = get_allocation ();

        get_style ()->paint_focus (get_window (),
                                   get_state (),
                                   allocation,
                                   *this,
                                   "button",
                                   xoff + 4, yoff + 4,
                                   allocation.get_width () - 8, allocation.get_height () - 8);
      }

      return true;
    }

    void
    SourceButton::create_label (Glib::ustring const& text, bool mnemonic)
    {
      m_label = new Gtk::Label ();
      m_label->set_selectable (false);
      m_label->set_single_line_mode ();
      if (mnemonic)
        {
          m_label->set_markup_with_mnemonic (text);
          m_label->set_mnemonic_widget (*this);
          m_label->set_use_underline ();
        }
      else
        {
          m_label->set_markup (text);
        }
      add (*m_label);
    }
}
