"""
    SALTS XBMC Addon
    Copyright (C) 2016 tknorris

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
import urllib
import urllib2
import urlparse
import os
import ssl
import socket
import json
import zipfile
import StringIO
import time
import utils
import log_utils
import kodi
import utils2
from db_utils import DB_Connection
from constants import VIDEO_TYPES
import xml.etree.ElementTree as ET

logger = log_utils.Logger.get_logger(__name__)
logger.disable()

CACHE_INSTALLED = kodi.has_addon('script.module.image_cache')
if CACHE_INSTALLED:
    import image_cache
    
db_connection = DB_Connection()
PLACE_POSTER = os.path.join(kodi.get_path(), 'resources', 'place_poster.png')
DEFAULT_FANART = utils2.art('fanart.jpg')
OMDB_ENABLED = kodi.get_setting('omdb_enable') == 'true'
TVMAZE_ENABLED = kodi.get_setting('tvmaze_enable') == 'true'
FANARTTV_ENABLED = kodi.get_setting('fanart_enable') == 'true'
BG_ENABLED = kodi.get_setting('bg_enable') == 'true'
POSTER_ENABLED = kodi.get_setting('poster_enable') == 'true'
BANNER_ENABLED = kodi.get_setting('banner_enable') == 'true'
CLEARART_ENABLED = kodi.get_setting('clearart_enable') == 'true'
THUMB_ENABLED = kodi.get_setting('thumb_enable') == 'true'
GIF_ENABLED = False
ZIP_CACHE = 24
OBJ_PERSON = 'person'
PROXY_TEMPLATE = 'http://127.0.0.1:{port}{action}'

class Scraper(object):
    protocol = 'http://'
    
    def _clean_art(self, art_dict):
        new_dict = {}
        for key in art_dict:
            if art_dict[key]:
                scheme, netloc, path, params, query, fragment = urlparse.urlparse(art_dict[key])
                new_dict[key] = urlparse.urlunparse((scheme, netloc, urllib.quote(path), params, query, fragment))
        return new_dict
    
    def _get_url(self, url, params=None, data=None, headers=None, cache_limit=1):
        if headers is None: headers = {}
        if data is not None:
            if isinstance(data, basestring):
                data = data
            else:
                data = urllib.urlencode(data, True)
        
        if not url.startswith('http'):
            url = '%s%s%s' % (self.protocol, self.BASE_URL, url)
        if params: url += '?' + urllib.urlencode(params)
        _created, cached_headers, html = db_connection.get_cached_url(url, data, cache_limit=cache_limit)
        if html:
            logger.log('Using Cached result for: %s' % (url))
            result = html
            res_headers = dict(cached_headers)
        else:
            try:
                headers['Accept-Encoding'] = 'gzip'
                logger.log('+++Image Scraper Call: %s, header: %s, data: %s cache_limit: %s' % (url, headers, data, cache_limit), log_utils.LOGDEBUG)
                request = urllib2.Request(url, data=data, headers=headers)
                response = urllib2.urlopen(request)
                result = ''
                while True:
                    data = response.read()
                    if not data: break
                    result += data
                res_headers = dict(response.info().items())
                if res_headers.get('content-encoding') == 'gzip':
                    result = utils2.ungz(result)
                db_connection.cache_url(url, result, data, res_header=res_headers)
            except (ssl.SSLError, socket.timeout) as e:
                logger.log('Image Scraper Timeout: %s' % (url))
                return {}
            except urllib2.HTTPError as e:
                if e.code != 404:
                    logger.log('HTTP Error (%s) during image scraper http get: %s' % (e, url), log_utils.LOGWARNING)
                return {}
            except Exception as e:
                logger.log('Error (%s) during image scraper http get: %s' % (str(e), url), log_utils.LOGWARNING)
                return {}

        try:
            if 'application/json' in res_headers.get('content-type', ''):
                return_data = utils.json_loads_as_str(result)
            else:
                # try/except to handle older responses that might be missing headers
                try: return_data = utils.json_loads_as_str(result)
                except ValueError: return_data = result
        except ValueError:
            return_data = ''
            if result:
                logger.log('Invalid JSON API Response: %s - |%s|' % (url, return_data), log_utils.LOGERROR)

        return return_data
        
class FanartTVScraper(Scraper):
    API_KEY = kodi.get_setting('fanart_key')
    CLIENT_KEY = kodi.get_setting('fanart_person_key')
    BASE_URL = 'webservice.fanart.tv/v3/'
    LANGS = {'en': 3, '00': 1, '': 2}

    def __init__(self):
        self.headers = {'api-key': self.API_KEY}
        if self.CLIENT_KEY:
            self.headers.update({'client-key': self.CLIENT_KEY})
        
    def get_movie_images(self, ids):
        art_dict = {}
        video_id = ids.get('tmdb') or ids.get('imdb')
        any_art = any((BG_ENABLED, BANNER_ENABLED, POSTER_ENABLED, CLEARART_ENABLED))
        if FANARTTV_ENABLED and self.API_KEY and any_art and video_id:
            url = '/movies/%s' % (video_id)
            images = self._get_url(url, headers=self.headers)
            if BG_ENABLED:
                art_dict['fanart'] = self.__get_best_image(images.get('moviebackground', []))
            
            if THUMB_ENABLED:
                art_dict['thumb'] = self.__get_best_image(images.get('moviethumb', []))

            if BANNER_ENABLED:
                art_dict['banner'] = self.__get_best_image(images.get('moviebanner', []))

            if POSTER_ENABLED:
                art_dict['poster'] = self.__get_best_image(images.get('movieposter', []))

            if CLEARART_ENABLED:
                art_dict['clearlogo'] = self.__get_best_image(images.get('hdmovielogo', []))
                if not art_dict['clearlogo']: art_dict['clearlogo'] = self.__get_best_image(images.get('movielogo', []))
                art_dict['clearart'] = self.__get_best_image(images.get('hdmovieclearart', []))
        
        return self._clean_art(art_dict)
    
    def get_tvshow_images(self, ids):
        art_dict = {}
        any_art = any((BG_ENABLED, BANNER_ENABLED, POSTER_ENABLED, CLEARART_ENABLED, THUMB_ENABLED))
        if FANARTTV_ENABLED and self.API_KEY and 'tvdb' in ids and ids['tvdb'] and any_art:
            url = '/tv/%s' % (ids['tvdb'])
            images = self._get_url(url, headers=self.headers)
            if BG_ENABLED:
                art_dict['fanart'] = self.__get_best_image(images.get('showbackground', []))
            
            if THUMB_ENABLED:
                art_dict['thumb'] = self.__get_best_image(images.get('tvthumb', []))
                
            if BANNER_ENABLED:
                art_dict['banner'] = self.__get_best_image(images.get('tvbanner', []))
            
            if POSTER_ENABLED:
                art_dict['poster'] = self.__get_best_image(images.get('tvposter', []))
            
            if CLEARART_ENABLED:
                art_dict['clearlogo'] = self.__get_best_image(images.get('hdtvlogo', []))
                if not art_dict['clearlogo']: art_dict['clearlogo'] = self.__get_best_image(images.get('clearlogo', []))
                art_dict['clearart'] = self.__get_best_image(images.get('hdclearart', []))
                if not art_dict['clearart']: art_dict['clearart'] = self.__get_best_image(images.get('clearart', []))
        
        return self._clean_art(art_dict)
    
    def get_season_images(self, ids):
        season_art = {}
        any_art = any((BANNER_ENABLED, POSTER_ENABLED, THUMB_ENABLED))
        if FANARTTV_ENABLED and self.API_KEY and 'tvdb' in ids and ids['tvdb'] and any_art:
            url = '/tv/%s' % (ids['tvdb'])
            images = self._get_url(url, headers=self.headers)
            seasons = set()
            for name in ['seasonposter', 'seasonthumb', 'seasonbanner']:
                seasons |= set([i['season'] for i in images.get(name, [])])
            
            for season in seasons:
                art_dict = {}
                if POSTER_ENABLED:
                    art_dict['poster'] = self.__get_best_image(images.get('seasonposter', []), season)
                
                if BANNER_ENABLED:
                    art_dict['banner'] = self.__get_best_image(images.get('seasonbanner', []), season)
                
                if THUMB_ENABLED:
                    art_dict['thumb'] = self.__get_best_image(images.get('seasonthumb', []), season)
                season_art[season] = self._clean_art(art_dict)
                
        return season_art
    
    def __get_best_image(self, images, season=None):
        best = None
        images = [image for image in images if image.get('lang') in ('en', '00', '')]
        if season is not None:
            images = [image for image in images if image.get('season') == season]
            
        images.sort(key=lambda x: (self.LANGS.get(x.get('lang'), 0), int(x['likes'])), reverse=True)
        if images:
            best = images[0]['url']
        return best

class TMDBScraper(Scraper):
    API_KEY = kodi.get_setting('tmdb_key')
    protocol = 'https://'
    BASE_URL = 'api.themoviedb.org/3'
    headers = {'Content-Type': 'application/json'}
    size = 'original'
    image_base = None
    
    def __get_image_base(self):
        if self.API_KEY:
            if self.image_base is None:
                url = '/configuration'
                params = {'api_key': self.API_KEY}
                js_data = self._get_url(url, params, headers=self.headers, cache_limit=24)
                try: self.image_base = '%s/%s/' % (js_data['images']['base_url'], self.size)
                except: self.image_base = None
        else:
            self.image_base = None
        return self.image_base
            
    def get_movie_images(self, ids, need=None):
        if need is None: need = ['fanart', 'poster']
        art_dict = {}
        any_art = any((BG_ENABLED, POSTER_ENABLED))
        if 'tmdb' in ids and ids['tmdb'] and any_art and self.__get_image_base():
            if CACHE_INSTALLED:
                images = image_cache.get_movie_images(ids['tmdb'])
                if images: logger.log('---Using Cached response for movie images')
            else:
                images = {}
            
            if not images:
                url = '/movie/%s/images' % (ids['tmdb'])