// search for 
#include "thumb.h"

// look for these divs:
//
// <div class="xxxx"...
//   data-ow="640"
//   data-oh="640"
//   data-ou="http://xxxxx"
// >
//
// data-xxx could be in any order so parse tag until end of tag and store
// each X=Y
//
// other option - low res but google served imaage in img tags
//
// <img ...
//  data-src="http://xxxx"
// >

typedef struct
{
   Eina_Bool in_div;
   Eina_Bool in_img;
   Eina_Hash *attr;
   void (*cb) (void *data, Eina_List *results_orig, Eina_List *results_cached);
   void *data;
   Eina_List *results_orig;
   Eina_List *results_cached;
   int magic;
} State;

static Eina_Bool
_cb_attr(void *data, const char *key, const char *val)
{
   State *state = data;

   // only if in div or img - add tag
   if (state->in_div || state->in_img)
     eina_hash_add(state->attr, key, strdup(val));
   return EINA_TRUE;
}

static Eina_Bool
_cb_tag(void *data, Eina_Simple_XML_Type type,
        const char *content, unsigned offset EINA_UNUSED, unsigned int len)
{
   State *state = data;
   const char *tags, *ow, *oh, *img;
   int w, h;
   Search_Result *res;

   if (type == EINA_SIMPLE_XML_OPEN)
     { // start sokme tag
        state->in_div = EINA_FALSE;
        state->in_img = EINA_FALSE;
        if (state->attr)
          { // clean up previous hash from previous tag if there
             eina_hash_free(state->attr);
             state->attr = NULL;
          }
        if (!strncmp(content, "div ", 4))
          { // we have a div - we're interested in those
             state->in_div = EINA_TRUE;
             state->attr = eina_hash_string_superfast_new(free);
          }
        else if (!strncmp(content, "img ", 4))
          { // we have an img - we're also interested in those
             state->in_img = EINA_TRUE;
             state->attr = eina_hash_string_superfast_new(free);
          }

        if ((state->in_div) || (state->in_img))
          { // pars the tag attributes
             tags = eina_simple_xml_tag_attributes_find(content, len);
             if (tags)
               { // pars a tag - div or img
                  eina_simple_xml_attributes_parse(tags,
                                                   len - (tags - content),
                                                   _cb_attr, state);
                  img = eina_hash_find(state->attr, "data-ou");
                  if (img)
                    { // this is an origial url entry with size
                       ow = eina_hash_find(state->attr, "data-ow");
                       oh = eina_hash_find(state->attr, "data-oh");
                       if ((ow) && (oh))
                         { // we need a width and height string and have them
                            w = atoi(ow);
                            h = atoi(oh);
                            res = calloc(1, sizeof(Search_Result));
                            if (res)
                              {
                                 res->w = w;
                                 res->h = h;
                                 res->url = strdup(img);
                                 state->results_orig =
                                   eina_list_append(state->results_orig, res);
                              }
                         }
                    }
                  else
                    {
                       img = eina_hash_find(state->attr, "data-src");
                       if (img)
                         { // this is a cached/scaled down version withotu size
                            res = calloc(1, sizeof(Search_Result));
                            if (res)
                              {
                                 res->url = strdup(img);
                                 state->results_cached =
                                   eina_list_append(state->results_cached, res);
                              }
                         }
                    }
               }
          }
     }
   return EINA_TRUE;
}

static void
_cb_query(void *data, const char *reply)
{ // parse the query result from searching
   State *state = data;
   Search_Result *res;

   if (!reply) goto err;
   eina_simple_xml_parse(reply, strlen(reply), EINA_TRUE, _cb_tag, state);
   if (state->attr)
     { // clean up any left over attributes hash
        eina_hash_free(state->attr);
        state->attr = NULL;
     }
   state->cb(state->data, state->results_orig, state->results_cached);
   // clean up lists of results we no longer need
   EINA_LIST_FREE(state->results_orig, res)
     {
        free(res->url);
        free(res);
     }
   EINA_LIST_FREE(state->results_cached, res)
     {
        free(res->url);
        free(res);
     }
err:
   elm_exit();
}

static Eina_Bool
_search_append(Eina_Strbuf *sb, const char *str, Eina_Bool hadword)
{ // take input string "as typed" and convert to part of query with +'s
  // like "this is a set of words" -> "this+is+a+set+of+words"
  // hadwords indicates if we had words before this call so to add a +
  // at the start to appeand to previous words
   const char *s;
   Eina_Bool word = EINA_FALSE;

   for (s = str; *s; s++)
     {
        // only use a-z, A-Z and 0-9 chars as words
        if (((*s >= 'a') && (*s <= 'z')) ||
            ((*s >= 'A') && (*s <= 'Z')) ||
            ((*s >= '0') && (*s <= '9')))
          {
             if (!word)
               { // we're not inside a word now
                  if (hadword)
                    { // we had a word before so add + between words
                       eina_strbuf_append_char(sb, '+');
                       word = EINA_FALSE;
                    }
               }
             eina_strbuf_append_char(sb, *s);
             word = EINA_TRUE;
             hadword = EINA_TRUE;
          }
        else word = EINA_FALSE;
        // stop when we hit a .
        if (*s == '.') break;
     }
   return hadword;
}

void
thumb_search_image(const char *str, void (*cb) (void *data, Eina_List *results_orig, Eina_List *results_cached), void *data)
{ // search for images given the str string
   Eina_Strbuf *query_buf;
   const char *query;
   State state = { 0 };

   state.cb = cb;
   state.data = data;
   state.magic = 1234567;

   query_buf = eina_strbuf_new();
   // add beginning of query
   eina_strbuf_append
     (query_buf,
      "http://www.google.com/search?as_st=y&tbm=isch&hl=en&as_q=");
   // add a search string like typed in like "this is a search"
   _search_append(query_buf, str, EINA_FALSE);
   // add rest of query
   eina_strbuf_append
     (query_buf,
      "&as_epq=&as_oq=&as_eq=&cr=&as_sitesearch=&safe=images&tbs=ift:jpg");
   query = eina_strbuf_string_get(query_buf);
   // send that query off and handle it in _cb_query - max 8M
   thumb_url_str_get(query, 8 * 1024 * 1024, _cb_query, &state);
   elm_run();
   eina_strbuf_free(query_buf);
}
