/*
   artist.c - Implements the Artist API
   See README for Copyright and License
*/

#include <string.h>
#include "lfm_helper.h"

extern const char *LASTFM_IMAGE_SIZES[];

extern LASTFM_TAG_INFO *_new_LASTFM_TAG_INFO();

void  LASTFM_free_artist_info(LASTFM_ARTIST_INFO *a){
	int i;	
	if(!a)return;
	if(a->name)free(a->name);
	if(a->image)free(a->image);
	if(a->image_url)free(a->image_url);
	if(a->summary)free(a->summary);
	if(a->similar){
		for(i=0;a->similar[i];i++)free(a->similar[i]);
		free(a->similar);
	}
	free(a);
}

static inline void free_LASTFM_ARTIST_INFO(LASTFM_ARTIST_INFO *a, void *n){
	LASTFM_free_artist_info(a);
}

void LASTFM_free_artist_info_list(LFMList *list){
	LFMList_foreach(list,(LFMFunc)free_LASTFM_ARTIST_INFO,NULL);
	LFMList_free(list);
}

LASTFM_ARTIST_INFO* _new_LASTFM_ARTIST_INFO(){
	LASTFM_ARTIST_INFO *a;
	a = malloc(sizeof(LASTFM_ARTIST_INFO));
	a->image     = NULL;
	a->image_url = NULL;
	a->image_size = 0;
	a->playcount  = 0;
	a->summary = NULL;
	a->similar = NULL;
	return a;
}

LASTFM_IMAGE_INFO *_new_LASTFM_IMAGE_INFO(){
	LASTFM_IMAGE_INFO *a;
	a = malloc(sizeof(LASTFM_IMAGE_INFO));
	a->title     = NULL;
	a->image     = NULL;
	a->image_url = NULL;
	a->image_size  = 0;
	a->thumbs_up   = 0;
	a->thumbs_down = 0;
	a->time        = 0;
	return a;
}

void LASTFM_free_image_info(LASTFM_IMAGE_INFO *i){
	if(i == NULL) return;
	if(i->title)     free(i->title);
	if(i->image)     free(i->image);
	if(i->image_url) free(i->image_url);
	free(i);
}

static inline void free_LASTFM_IMAGE_INFO(LASTFM_IMAGE_INFO *a, void *n){
	LASTFM_free_image_info(a);
}

void LASTFM_free_image_info_list(LFMList *list){
	LFMList_foreach(list,(LFMFunc)free_LASTFM_IMAGE_INFO,NULL);
	LFMList_free(list);
}

void LASTFM_print_image_info_list(FILE *out, LFMList *list){
	LFMList *i;
	LASTFM_IMAGE_INFO *r;
	int count;
	if(list == NULL)return;

	count = 0;
	for(i=list;i;i=i->next){
		r = i->data;
		printf("Image[%02i] Title=\"%s\", Image Size = %zu,"
			" Thumbs Up = %i, Thumbs Down = %i, Image URL = %s\n",
			count,r->title,r->image_size,r->thumbs_up,r->thumbs_down,
			r->image_url);
		count ++;
	}
}

void LASTFM_print_artist_info(FILE *out, LASTFM_ARTIST_INFO *a){
	int i;
	if(a== NULL)return;
	fprintf(out,"name       = %s\n",a->name);
	fprintf(out,"playcount  = %u\n",a->playcount);
	// Obviously you cant just print out the binary file
	// so just print out its size 
	fprintf(out,"image url  = %s\n",a->image_url);
	fprintf(out,"image size = %zu\n",a->image_size);
	fprintf(out,"summary    = %s\n",a->summary);
	fprintf(out,"similar :\n");
	if(a->similar != NULL){
		for(i=0;a->similar[i];i++){
			printf("           %i:%s\n",i,a->similar[i]);
		}
	}

}

int LASTFM_artist_get_top_tags(LASTFM_SESSION *s, const char *artist, LFMList **result){
	XMLNode *xml=NULL, *xi, *xj;
	WebData *data = NULL;
	LASTFM_TAG_INFO *a = NULL;
	LFMList *out = NULL;
	char *buffer, *q_artist;
	int rv = LASTFM_STATUS_ERROR;

	if(s == NULL || strisspace(artist) ) 
		return LASTFM_STATUS_INVALID;
	
	q_artist = curl_easy_escape(s->curl,artist,0);

	buffer = malloc(LARGE_BUFFER);
	snprintf(buffer,LARGE_BUFFER,
		"%s?method=artist.gettoptags&api_key=%s&artist=%s&autocorrect=1",
		API_ROOT,s->api_key,q_artist);
	curl_free(q_artist);
	
	data = lfm_helper_get_page(buffer,s);
	free(buffer);

	xml = tinycxml_parse(data->page);
	if(lfm_helper_get_status(s,xml))goto done;

	xi = xmlnode_get(xml, CCA { "lfm","toptags","tag",NULL },NULL,NULL);
	for(;xi;xi=xi->next){
		a = _new_LASTFM_TAG_INFO();
		LFMList_append(&out,a);

		xj = xmlnode_get(xi,CCA { "tag","name",NULL } ,NULL,NULL);
		if(xj && xj->content)
			a->name = unescape_HTML(strdup(xj->content));

		xj = xmlnode_get(xi,CCA {"tag","url",NULL},NULL,NULL);
		if(xj && xj->content)
			a->url = strdup(xj->content);
		
		xj = xmlnode_get(xi,CCA { "tag","count",NULL } ,NULL,NULL);
		if(xj && xj->content)
			a->count = atoi(xj->content);
	}

	rv = LASTFM_STATUS_OK;
	done:
	s->fraction = -1;
	xmlnode_free(xml);
	lfm_helper_free_page(data);
	*result = out;
	return rv;
}

int LASTFM_artist_get_images(LASTFM_SESSION *s, const char *artist, unsigned size, 
						unsigned limit, unsigned page, 
						LFMList **results){
	WebData *data = NULL;
	WebData *image;
	XMLNode *xml = NULL, *xi, *xj;
	char *quote_artist;
	char *buffer;
	int j,download;
	unsigned img_size = 0;
	int tpages=0,rpages = 0,cpage=0;
	LASTFM_IMAGE_INFO *r = NULL;
	LFMList *i,*out = NULL;

	if(s == NULL){
		strcpy(s->status,"Invalid session handle");
		return -1;
	}
	if(artist == NULL){
		strcpy(s->status,"Artist name not provided");
		return -1;
	}
	
	if(size >= LASTFM_IMAGE_URL_COUNT ){
		strcpy(s->status,"Invalid image size");
		return -1;
	}

	buffer = malloc(LARGE_BUFFER);
	quote_artist = curl_easy_escape(s->curl,artist,0);
	j = snprintf(buffer,LARGE_BUFFER,
		"%s?method=artist.getimages&api_key=%s&artist=%s&page=%u",
			API_ROOT,s->api_key,quote_artist,page);
	curl_free(quote_artist);

	if(limit)
		j+= snprintf(buffer+j,LARGE_BUFFER-j,"&limit=%u",limit);

	data = lfm_helper_get_page(buffer,s);
	free(buffer);

	xml = tinycxml_parse(data->page);
	if(lfm_helper_get_status(s,xml))goto done;

	xi = xmlnode_get(xml,CCA { "lfm","images",NULL},"totalPages",NULL);
	if(xi && xi->content)
		tpages = atoi(xi->content);

	xi = xmlnode_get(xml,CCA { "lfm","images",NULL},"page",NULL);
	if(xi && xi->content)
		cpage = atoi(xi->content);

	rpages = tpages - cpage;

	if(size < LASTFM_IMAGE_COUNT){
		img_size = size;
		download = 1;
	}else if(size < LASTFM_IMAGE_URL_COUNT){
		img_size = size - LASTFM_IMAGE_URL_OG;
		download = 0;
	}

	xi = xmlnode_get(xml,CCA { "lfm","images","image",NULL},NULL,NULL);
	for(;xi;xi= xi->next){
		r = _new_LASTFM_IMAGE_INFO();

		xj = xmlnode_get(xi,CCA {"image","title",NULL},NULL,NULL);
		if(xj && xj->content)
			r->title = unescape_HTML(strdup(xj->content));

		/* Try get the biggest image possible */	
		for(j=img_size;LASTFM_IMAGE_SIZES[j];j++){
			xj = xmlnode_get(xi,CCA { "image","sizes","size",NULL } ,"name",LASTFM_IMAGE_SIZES[j]);
			if(xj && xj->content) {
				r->image_url = strdup(xj->content);
				break;
			}
		}
	
		xj = xmlnode_get(xi,CCA { "image","votes","thumbsup",NULL}, NULL,NULL);
		if(xj && xj->content)
			r->thumbs_up = atoi(xj->content);

		xj = xmlnode_get(xi,CCA { "image","votes","thumbsdown",NULL}, NULL,NULL);
		if(xj && xj->content)
			r->thumbs_down = atoi(xj->content);

		LFMList_append(&out,r);
	}
	
	/* Get Images */
	if(download){
		for(i=out;i;i=i->next){
			r = i->data;
			image = lfm_helper_get_page(r->image_url,s);
			if(image && image->size > 1024){
				r->image  = malloc(image->size);
				memcpy(r->image,image->page,image->size);
				r->image_size = image->size;
			}
			lfm_helper_free_page(image);
		}
	}

	done:
	*results = out;
	s->fraction = -1;
	lfm_helper_free_page(data);
	xmlnode_free(xml);
	return rpages;
}

LASTFM_ARTIST_INFO *LASTFM_artist_get_info(LASTFM_SESSION *s, const char *artist, const char *lang){
	LASTFM_ARTIST_INFO *a = NULL;
	WebData *data = NULL;
	WebData *image;
	XMLNode *xml = NULL, *xi, *xj;
	char *art_tmp;
	char *buffer;
	int i;

	if(s == NULL || artist == NULL) return NULL;

	buffer = malloc(LARGE_BUFFER);
	art_tmp = curl_easy_escape(s->curl,artist,0);
	i = snprintf(buffer,LARGE_BUFFER,
		"%s?method=artist.getinfo&api_key=%s&artist=%s&autocorrect=1",
			API_ROOT,s->api_key,art_tmp);
	curl_free(art_tmp);

	if(s->username)
		i += snprintf(buffer+i,LARGE_BUFFER-i,"&username=%s",s->username);

	if(lang)
		i += snprintf(buffer+i,LARGE_BUFFER-i,"&lang=%s",lang);

	data = lfm_helper_get_page(buffer,s);
	free(buffer);

	xml = tinycxml_parse(data->page);
	if(lfm_helper_get_status(s,xml))goto done;

	a = _new_LASTFM_ARTIST_INFO();

	xi = xmlnode_get(xml,CCA {"lfm","artist",NULL},NULL,NULL);

	xj = xmlnode_get(xi, CCA {"artist","name",NULL},NULL,NULL);
	if(xj && xj->content)
		a->name = unescape_HTML(strdup(xj->content));

	xj = xmlnode_get(xi,CCA { "artist", "stats","userplaycount",NULL},NULL,NULL);
	if(xj && xj->content){
		a->playcount = atoi(xj->content);
	} else {
		xj = xmlnode_get(xi,CCA { "artist", "stats","playcount",NULL},NULL,NULL);
		if(xj && xj->content)
			a->playcount = atoi(xj->content);
	}

	/* Try get the biggest image possible */	
	for(i=0;LASTFM_IMAGE_SIZES[i];i++){
		xj = xmlnode_get(xi,CCA { "artist","image",NULL } , "size",LASTFM_IMAGE_SIZES[i]);
		if(xj && xj->content) {
			a->image_url = strdup(xj->content);
			break;
		}
	}

	if(a->image_url){
		/* Get Image */
		image = lfm_helper_get_page(a->image_url,s);
		if(image && image->size > 1024){
			a->image  = malloc(image->size);
			memcpy(a->image,image->page,image->size);
			a->image_size = image->size;
		}
		lfm_helper_free_page(image);
	}

	/* Get Summary */
	xj = xmlnode_get(xi,CCA {"artist","bio","summary",NULL},NULL,NULL);
	if(xj && xj->content){
		a->summary = unescape_HTML(strdup(xj->content));
	}

	/* Get the similar artist names */
	xi = xmlnode_get(xi,CCA {"artist","similar","artist",NULL},NULL,NULL);
	a->similar = malloc(sizeof(char *) * 20);
	for(i=0;xi;xi=xi->next){
		xj = xmlnode_get(xi,CCA {"artist","name",NULL},NULL,NULL);
		if(xj)
			a->similar[i] = unescape_HTML(strdup(xj->content));
		i++;
	}
	a->similar[i] = NULL;

	done:
	s->fraction = -1;
	lfm_helper_free_page(data);
	xmlnode_free(xml);
	return a;
}
