/**
 *  GraphTFT plugin for the Video Disk Recorder 
 * 
 *  imlibrenderer.c - A plugin for the Video Disk Recorder
 *
 *  (c) 2004 Lars Tegeler, Sascha Volkenandt  
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 * $Id: imlibrenderer.c,v 1.2 2004/05/08 18:55:45 tegeler Exp $
 *
 **/

/* standard */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>

#include <string>
#include <vector>
// ostringstream
#include <sstream>

#include <string>
#include <utility>
#include <iostream>

#include "imlibrenderer.h"
#include "setup.h"
#include "theme.h"
#include "common.h"

// allways use list, string, cout, cerr, and endl
using std::string;
using std::cout;
using std::cerr;
using std::endl;


// -------------------------------------------------//

ImlibRenderer::ImlibRenderer() :  _width(720), _height(576)
{
  Imlib_Context ctx = imlib_context_new();
  imlib_context_push(ctx);
		  
	
  // cache
  imlib_set_cache_size(4096 * 1024);
  imlib_set_font_cache_size(2048 * 1024);

  
  // font
  std::ostringstream path; path <<  GraphTFTSetup.PluginConfPath << "/graphTFT/fonts/";
  imlib_add_path_to_font_path(path.str().c_str());
  
  // new image
  _cur_image = new_imlib_image();
  imlib_context_set_image(_cur_image);
  _render_image = new_imlib_image();

  // clear the image
  //UINT8 *dataptr = (UINT8 *) imlib_image_get_data();
  //memset(dataptr, 0, _width * _height * 4);
  //imlib_image_put_back_data( (DATA32 *) dataptr);

  // nicer scaling
//  imlib_context_set_anti_alias(1);

  // dither for depths < 24bpp
//  imlib_context_set_dither(1);

	imlib_set_color_usage(256);
}

ImlibRenderer::~ImlibRenderer()
{
	
	;
}

//---------------------------------------------------------------------------------

Imlib_Image ImlibRenderer::new_imlib_image()
{
  return imlib_create_image(_width, _height);
}

void ImlibRenderer::set_context_to_buffer(Imlib_Image img)
{
	imlib_context_set_image(img);
}

void ImlibRenderer::refresh()
{
	//free old render image
	set_context_to_buffer(_render_image);
	//imlib_free_image();

  	int height = GraphTFTSetup.VdrHeight;
    	int widht = GraphTFTSetup.VdrWidht;
	int x = GraphTFTSetup.VdrX;
	int y = GraphTFTSetup.VdrY;
        imlib_blend_image_onto_image(_cur_image, 0, 0,0, 720, 576, x + widht, y + height, 720 - x - (2 * widht), 576 - y - ( 2 * height) );

	//change cur_image to render_image
	//_render_image = _cur_image;

	//set new context
	//_cur_image = new_imlib_image();
	//set_context_to_buffer(_cur_image);
	clear();
}

void ImlibRenderer::clear()
{
	//clear the current image
	set_context_to_buffer(_cur_image);
	imlib_free_image();
	_cur_image = new_imlib_image();
	set_context_to_buffer(_cur_image);
}


//----------------------------------------------------------------------------------

void ImlibRenderer::image(const char* fname, int x, int y, bool fullpath)
{
  Imlib_Image new_image;
  int width = 0;
  int height = 0;
  std::ostringstream path;

  if (fullpath)
	path << fname;
  else
  	path << GraphTFTSetup.PluginConfPath << "/graphTFT/themes/" << GraphTFTTheme.getDir() << "/" << fname; 
  new_image = imlib_load_image(path.str().c_str());
  if (!new_image){ /* note, the imlib image context isn't really restored after
                     calling this method, it's just set to whatever 'image'
                     parameter is */
    std::cerr << "The image " << path.str() 
	      << " could not be loaded." << std::endl;
    if ((x==0) && (y==0)) {
      new_image = imlib_create_image(720, 576);
    } else {
      new_image = imlib_create_image(1, 1);
    }
    imlib_context_set_image(new_image);
    imlib_image_clear_color(0,0,0,((x==0)&&(y==0))?255:0);
  }

  imlib_context_set_image(new_image);
  width = imlib_image_get_width();
  height = imlib_image_get_height();
  
  imlib_context_set_image(_cur_image);
  imlib_blend_image_onto_image(new_image, 0, 0, 0, width, height, x, y, width, height);
  imlib_context_set_image(new_image);
  imlib_free_image();
  imlib_context_set_image(_cur_image);
}


int ImlibRenderer::text(const char *text, const char *font_name,int size, int align, int x, int y, int r, int g, int b, int widht, int height, int lines)
{
	
	//FIX ME, FIX ME, FIX ME ;-)
	string tmp2;
	string tmp = text;

	string in = tmp;
	const char out[1024] = "";
	int l1, l2;
	l1 = in.length();
	l2 = 1024;

	if ( GraphTFTSetup.Iso2Utf ){
        	if ( !isolat1ToUTF8((unsigned char*)out , &l2, (unsigned char*)in.c_str(),&l1) ){
			tmp = strdup(out);
			tmp.resize(l2);
		}
	}

	int lineHeight, textWight, pos, index, maxLines;
	int widht3=0;
	int lineCount = -1;
  	Imlib_Font font;

    	std::ostringstream font_name_size;
	font_name_size <<  font_name << "/" << size;

    	font = imlib_load_font((font_name_size.str()).c_str());
      	if (font){
		imlib_context_set_font(font);
		imlib_context_set_image(_cur_image);
		imlib_context_set_color(r, g, b, 255);
		
		imlib_get_text_size(tmp.c_str(), &textWight, &lineHeight);
		if (lines != 0)
			maxLines = lines;
		else
			maxLines = height / lineHeight;
		lineCount=1;
		while ( textWight > widht && textWight > 0 && lineCount <= maxLines && widht >= 0 )
		{
			widht3 =0;
			for(index = 1; widht3 < widht; index++)
			{
				string tmp3 = tmp.substr(0,index);
				imlib_get_text_size(tmp3.c_str(), &widht3, &lineHeight);
			}
			tmp2 = tmp.substr(0,index+1);
			pos = tmp2.rfind(' ');
			if (pos != -1 && pos != 0 && lineCount != maxLines )
			{
				tmp2.resize(pos);
				tmp = tmp.substr(pos+1);
			}else
			{
				tmp2.resize(index-2);
				tmp = tmp.substr(index-2);
			}

			imlib_get_text_size(tmp2.c_str(), &textWight, &lineHeight);
			if (align == 0)
				imlib_text_draw(x, y + (lineHeight * (lineCount-1)), tmp2.c_str() );
			else if (align == 1)
				imlib_text_draw(x + (widht - textWight) / 2, y + (lineHeight * (lineCount-1)), tmp2.c_str() );
			else
				imlib_text_draw(x + widht - textWight, y + (lineHeight * (lineCount-1)), tmp2.c_str() );
			lineCount++;
			imlib_get_text_size(tmp.c_str(), &textWight, &lineHeight);
		}
        	if (lineCount <= maxLines && tmp.size() > 0){
			if (align == 0)
				imlib_text_draw(x, y + (lineHeight * (lineCount-1)), tmp.c_str());
			else if (align == 1)
				imlib_text_draw(x + (widht - textWight) / 2, y + (lineHeight * (lineCount-1)), tmp.c_str());
			else
				imlib_text_draw(x + widht - textWight, y + (lineHeight * (lineCount-1)), tmp.c_str());
		}
		else
			lineCount--;
	    	imlib_free_font();
	}
	else
		std::cerr << "The font " << font_name << " could not be loaded." << std::endl;	
	return lineCount;	
}

void ImlibRenderer::rectangle(int x, int y, int width, int height, int r, int g, int b, int a) 
{
	imlib_context_set_image(_cur_image);
	imlib_context_set_color(r, g, b, a);
	imlib_image_fill_rectangle(x, y, width, height);
}


//--------------------------------------------------------------------------------------

void ImlibRenderer::dumpImage2File(const char* fname, int dumpWidth, int dumpHeight)
{
	std::ostringstream path; path << "/tmp"; 

	// check if local directory structure exist, else create it.
  	if (!file_exists(path.str().c_str())) {
    		mkdir(path.str().c_str(), 0777);
  	}

	/* an image handle */
  	Imlib_Image new_image = imlib_create_image(dumpWidth, dumpHeight);

	/* get width and heigt*/
	imlib_context_set_image(_render_image);
	int width = imlib_image_get_width();
	int height = imlib_image_get_height();

	imlib_context_set_image(new_image);
	imlib_blend_image_onto_image(_render_image, 0, 0, 0, width, height, 0, 0, dumpWidth, dumpHeight);

	/* save the image */
	imlib_image_set_format("png");
	path << "/graphTFT.png";
	imlib_save_image(path.str().c_str());

	imlib_free_image();
	imlib_context_set_image(_render_image);
}
