# -*- coding: utf-8 -*-
# Copyright 2009 Martin Borho <martin@borho.net>
# GPL - see License.txt for details
from urllib import urlencode, quote_plus
from baas.core.plugins import Plugin
from baas.core.helpers import strip_tags, xmlify, htmlentities_decode, load_url
 
try:
    # appengine
    from django.utils import simplejson
except:
    import simplejson
 
class Gsearch (Plugin):
 
    def __init__(self, config, format='xmpp'):
        super(Gsearch,self).__init__(config, format)
        self.result_limit = 8
 
    def get_map(self):
        """
            returns the command map for the plugin
        """
        cmd_map = [
            ('gnews',self.news), 
            ('gweb', self.web),
            ('metacritic', self.metacritic),
            ('imdb', self.imdb),
            ('wikipedia', self.wikipedia),
            ('wiktionary', self.wiktionary),
            ('amazon', self.amazon)]
        return cmd_map
 
    def get_limits(self):
        """
            returns the limit map for the plugin commands
            for e.g. several result pages
        """
        limit_map = [
            ('gnews',self.result_limit), 
            ('gweb', self.result_limit),
            ('metacritic', self.result_limit),
            ('imdb', self.result_limit),
            ('wikipedia', self.result_limit),
            ('wiktionary', self.result_limit),
            ('amazon', self.result_limit)]
        return limit_map
 
    def get_help(self):
        """
            returns the help text for the plugin
        """
        additional = '''gnews and gweb can be also combined with lang-codes, like #de, #en, #es etc:
gnews:hamburg #de
gweb:xmpp #de
 
IMDb search can be narrowed down with #en, #de, #es, #pt, #it or #fr
Amazon search with #com, #co.uk, #co.jp, #cn, #de, #ca, #at or #fr
The different wikipedia or wiktionary versions can be selected via #en, #de, #fr etc.'''
 
        return {
            'commands': [
                'gnews:word - google news search',
                'gweb:word - google web search',
                'metacritic:title - search for reviews on metacritc.com',
                'imdb:title - search for movie on IMDb',
                'wikipedia:thing - search on wikipedia',
                'wiktionary:word - search on wiktionary',
                'amazon: product - search for products on amazon'],
            'additional': [additional],
        }
 
    def _api_request(self, mode, params):
 
        url_params = urlencode( params )
        api_url = 'http://ajax.googleapis.com/ajax/services/search/'+mode+'?%s' % (url_params)
 
        response = load_url(api_url)
        api_response  = simplejson.loads(response)
        if api_response.get('responseStatus') == 200:
            return api_response
        else:
            return None
 
    def _extract_hits(self, result):
        if result:
            hits = result.get('responseData',{}).get('results')
            # handle single result
            if type(hits) == dict:
                hits = [hits]
            return hits
        else:
            return None
 
    def _build_query_term(self, term):
        return 'intitle:' + ' intitle:'.join(term.split())+' '
 
    def web(self, term):
        '''
        searches web by yahoo
        '''
        term = term.strip()
        lang = 'en'
        page = 1
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        params = {
                'v':'1.0', 
                'q':term.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit
                }
 
        if lang.startswith('lang_'):
            # specific lang code
            params['lr'] = lang
        else:
            # short lang code
            params['hl'] = lang 
            params['gl'] = lang
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Web search for %s\n' % term
        return self.render(data=hits, title=title)
 
    def news(self, term):
        '''
        searches news
        '''
        term = term.strip()
        lang = None
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        params = {
                'v':'1.0', 
                'q':term.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit
                #'scoring':'d',
                }
 
        if lang: 
            params['ned'] = lang
 
        response = self._api_request('news', params)
        hits = self._extract_hits(response)
 
        title = 'Google news search for %s\n' % term
        return self.render(data=hits, title=title)        
 
    def metacritic(self, term):
        '''
        searches metacritic
        '''
        term = term.strip()
        if term:
            (term, page) = self.extract_page_param(term)                            
 
        query = 'site:metacritic.com intitle:reviews %s' % self._build_query_term(term)
        params = {
                'v':'1.0', 
                'q':query.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit
                }
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Reviews for "%s"\n' % term
        return self.render(data=hits, title=title)        
 
    def imdb(self, term):
        '''
        searches metacritic
        '''
        term = term.strip()
 
        lang = None
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        tld = lang if lang and lang != 'en' else 'com' 
 
        query = 'site:imdb.%s inurl:"/title/" %s' % (tld, self._build_query_term(term))
        params = {
                'v':'1.0', 
                'q':query.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit                
                }
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Results on IMDb for "%s"\n' % term
        return self.render(data=hits, title=title)        
 
    def wikipedia(self, term):
        '''
        searches metacritic
        '''
        term = term.strip()
        lang = 'en'
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        query = 'site:%s.wikipedia.org inurl:"/wiki/" %s' % (lang, term)
        params = {
                'v':'1.0', 
                'q':query.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit
                }
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Wikipedia entries for "%s"\n' % term
        return self.render(data=hits, title=title)    
 
    def wiktionary(self, term):
        '''
        searches metacritic
        '''
        term = term.strip()
        lang = 'en'
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        query = 'site:%s.wiktionary.org inurl:"/wiki/" %s' % (lang, term)
        params = {
                'v':'1.0', 
                'q':query.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit,
                'hl':lang,
                'gl':lang
                }
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Wiktionary entries for "%s"\n' % term
        return self.render(data=hits, title=title)    
 
 
    def amazon(self, term):
        '''
        searches metacritic
        '''
        term = term.strip()
 
        lang = None
 
        if term:
            (term, page) = self.extract_page_param(term)                            
            if term.find('#')+1:
                term, lang = term.split('#',1)
                term = term.strip()
 
        tld = lang if lang else 'com' 
 
        query = 'site:www.amazon.%s " %s' % (tld, self._build_query_term(term))
        params = {
                'v':'1.0', 
                'q':query.encode('utf-8').lower(),
                'rsz':'large',
                'start':(page-1)*self.result_limit                
                }
 
        tld_lang_map = { 'co.uk':'lang_en','com':'lang_en', 'fr':'lang_fr',
                            'de':'lang_de', 'co.jp':'lang_ja'}
        params['lr'] = tld_lang_map.get(lang,'')            
 
        response = self._api_request('web', params)
        hits = self._extract_hits(response)
 
        title = 'Products on Amazon for "%s"\n' % term
        return self.render(data=hits, title=title) 
 
    def render_xmpp(self, hits, title):
        '''
        renders the result for xmpp responses
        '''
        result = title+"\n"
        if hits:
            for row in hits:
                title = row['titleNoFormatting']
                if row.get('publisher'):
                    title = "%s: %s" % (row.get('publisher'), title)
                result += "%s - %s\n" % (htmlentities_decode(title), row['unescapedUrl'])
        else:
            result += 'No hits found!'
        return strip_tags(result)
 
    def render_wave(self, hits, title):
        '''
        renders the result for wave responses
        '''
        result = " <br/><br/><b>%s</b><br/>" % xmlify(title)
        if hits:
            for row in hits:
                title = row['titleNoFormatting']
                if row.get('publisher'):
                    title = "%s: %s" % (row.get('publisher'), title)
                title = xmlify(htmlentities_decode(title))
                result += '<a href="%s">%s</a><br/><br/>' % (xmlify(row['unescapedUrl']), title)
        else:
            result += 'No hits found!'
        return result