/***************************** LICENSE START ***********************************

 Copyright 2013 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQIconProvider.h"

#include <QDebug>
#include <QImage>
#include <QImageReader>
#include <QPainter>

#include "Folder.h"
#include "IconClass.h"
#include "IconObject.h"
#include "MvQTheme.h"

#include <algorithm>

//This array defines the avaiable icon sizes
static int sizeArr[]={12,16,24,32,48,64,96};

static MvQIcon unknownIcon(":/desktop/unknown.svg");
static MvQIcon linkIcon(":/desktop/link.svg");
static MvQIcon linkBrokenIcon(":/desktop/link_broken.svg");
static MvQIcon lockIcon(":/desktop/padlock.svg");
static MvQIcon warningIcon(":/desktop/warning.svg");
static MvQIcon errorIcon(":/desktop/error.svg");
static MvQIcon bookmarkGroupIcon(":/desktop/bookmark_group.svg");
static MvQIcon embeddedIcon(":/desktop/embedded.svg");

int MvQIconProvider::defaultSize_=32;
std::map<string,MvQIcon*> MvQIconProvider::icons_;  
std::map<string,Folder*> MvQIconProvider::folders_; 
vector<int> MvQIconProvider::sizes_(sizeArr,sizeArr+ sizeof(sizeArr)/sizeof(sizeArr[0]));

//===========================================
// 
// MvQIcon
//
//===========================================

MvQIcon::MvQIcon(QString path) : path_(path)
{
}

QPixmap MvQIcon::pixmap(int size)
{
 	 map<int,QPixmap>::iterator it=pixmaps_.find(size);
	 if(it != pixmaps_.end())
	   	return it->second;
	 else
	 {
	   	QPixmap pix;
		QImageReader imgR(path_);
		if(imgR.canRead())
		{
			imgR.setScaledSize(QSize(size,size));
			QImage img=imgR.read();
			pix=QPixmap::fromImage(img);
		}
		else
		{
		  	qDebug() << path_;
		  	pix=unknownIcon.pixmap(size);		
		} 
		
		pixmaps_[size]=pix;
		return pix;
	 }
	 return QPixmap();
}	 
  
/*QPixmap MvQIcon::fadedPixmap(int size)
{
 	 map<int,QPixmap>::iterator it=fadedPixmaps_.find(size);
	 if(it != fadedPixmaps_.end())
	   	return it->second;
	 else
	 {	   	
	   	QPixmap pix=pixmap(size);
		QImage img=pix.toImage();
		greyOut(img);
		pix=QPixmap::fromImage(img);
		fadedPixmaps_[size]=pix;
		return pix;
	 }
	 return QPixmap();
}*/	 


QPixmap MvQIcon::pixmap(IconObject *obj,int size,bool checkEmbedded)
{  	
	QPixmap pix=pixmap(size);
	
	if(obj->temporary())
	{
		QImage img=pix.toImage();
		img.invertPixels();
		return QPixmap::fromImage(img);
	}	
	
	if(obj->isLink())
	{
		QImage img=pix.toImage();
		QPainter p(&img);
		int subSize=(size<=32)?(size/2):static_cast<int>((static_cast<float>(size*0.4)));
		
		if(obj->isBrokenLink())
		{	
			greyOut(img);
			QRect r(0,0,subSize,subSize);
			p.drawPixmap(QPoint(0,size-subSize),
					     linkBrokenIcon.pixmap(subSize),r);
		}
		else
		{  
			QRect r(0,0,subSize,subSize);
			p.drawPixmap(QPoint(0,size-subSize),
				linkIcon.pixmap(subSize),r);
		}	
	
		pix=QPixmap::fromImage(img);
	}
	if(obj->locked())
	{
	  	QImage img=pix.toImage();
		QPainter p(&img);
		int subSize=(size<=32)?(size/2):static_cast<int>((static_cast<float>(size*0.4)));
		
		QRect r(0,0,subSize,subSize);
		p.drawPixmap(QPoint(size-subSize,size-subSize),
			lockIcon.pixmap(subSize),r);	
		
		pix=QPixmap::fromImage(img);
	}
	if(checkEmbedded && obj->isEmbedded())
	{			
		int subSize=size/2;
		QPixmap emb(size+subSize/2,size);
		emb.fill(Qt::transparent);	
		QPainter p(&emb);
	
		QRect r(0,0,size,size);
		p.drawPixmap(QPoint(0,0),pix,r);
		r=QRect(0,0,subSize,subSize);
		p.drawPixmap(QPoint(size-subSize/2,0), 
			     embeddedIcon.pixmap(subSize),r);	
	
		pix=emb;
	}	
			
	return pix;
} 


QPixmap MvQIcon::greyedOutPixmap(IconObject *obj,int size)
{  	
	QPixmap pix=pixmap(obj,size,false);
	QImage img=pix.toImage();
	greyOut(img);
	return QPixmap::fromImage(img);
}		
	
void MvQIcon::greyOut(QImage &img)
{
	int w=img.width();
	int h=img.height();
	QRgb c;
	int g;
	int gBase=MvQTheme::colour("itemview_main","faded_base").red();
	float gFactor=(255.-gBase)/255.;
	
	for(int i=0; i < w; i++)
	  	for(int j=0; j < h; j++)
		{
		  	c=img.pixel(i,j);
			if(qAlpha(c) != 0)
			{
			  	//g=qGray(c);
				g=(qRed(c)+qGreen(c)+qBlue(c))/3;
				g=gBase+gFactor*static_cast<float>(g);				
				img.setPixel(i,j,qRgb(g,g,g));
			}	
		}	
}	

//===========================================
// 
// MvQIconProvider
//
//===========================================

MvQIconProvider::MvQIconProvider()
{	
}

MvQIcon* MvQIconProvider::icon(const IconClass& kind)
{
	map<string,MvQIcon*>::iterator it=icons_.find(kind.name());
	if(it != icons_.end()) 
		return it->second;
			
  	MvQIcon *p=new MvQIcon(QString::fromStdString(kind.pixmap().str()));	  
	icons_[kind.name()]=p;
	return p;
}

MvQIcon* MvQIconProvider::icon(const std::string& kind)
{
	map<string,MvQIcon*>::iterator it=icons_.find(kind);
	if(it != icons_.end()) 
		return it->second;
	
	if(IconClass::isValid(kind))
	{  
		const IconClass& ic=IconClass::find(kind);
	  	MvQIcon *p=new MvQIcon(QString::fromStdString(ic.pixmap().str()));	  
		icons_[kind]=p;			
		return p;
	}
	return &unknownIcon;
}

QPixmap MvQIconProvider::pixmap(const std::string& type,int size)
{
	return icon(type)->pixmap(size);
}

QPixmap MvQIconProvider::pixmap(const IconClass& kind,int size)
{
	return icon(kind)->pixmap(size);
}

QPixmap MvQIconProvider::pixmap(IconObject *obj,int size,bool checkEmbedded)
{
	return (obj)?icon(obj->iconClass())->pixmap(obj,size,checkEmbedded):unknownIcon.pixmap(size);
}

QPixmap MvQIconProvider::greyedOutPixmap(IconObject *obj,int size)
{
	return (obj)?icon(obj->iconClass())->greyedOutPixmap(obj,size):unknownIcon.pixmap(size);
}

QPixmap MvQIconProvider::bookmarkPixmap(string fullName,int size)
{
	if(fullName == "FOLDERGROUP")
		return bookmarkGroupIcon.pixmap(size);
	
	std::map<string,Folder*>::iterator it=folders_.find(fullName);
	if(it != folders_.end())
	{
	  	if(it->second)	  
	  		return pixmap(it->second,size);
		else
		{
			folders_.erase(it);
		  	return warningIcon.pixmap(size);
		}	
	}
	else
	{  	
		Folder *folder=Folder::folder(fullName,false);	
		folders_[fullName]=folder;
		if(folder)
			return pixmap(folder,size);
		else 
		  	return warningIcon.pixmap(size);
	}	
	
	return warningIcon.pixmap(size);
}  

QPixmap MvQIconProvider::lockPixmap(int size)
{
	 return lockIcon.pixmap(size);  
}  

QPixmap MvQIconProvider::warningPixmap(int size)
{
	 return warningIcon.pixmap(size);  
} 

QPixmap MvQIconProvider::errorPixmap(int size)
{
	 return errorIcon.pixmap(size);  
} 

static MvQIconProvider	iconProvider;	