import json
import requests

from bs4 import BeautifulSoup
from .translator import GoogleTranslate


class imdb:

    @staticmethod
    def has_key(data, key):
        if isinstance(data, dict):
            if key in data:
                return True
            return any(imdb.has_key(v, key) for v in data.values())

        elif isinstance(data, list):
            return any(imdb.has_key(item, key) for item in data)

        return False

    @staticmethod
    def get_info(id, **kwargs):

        print('getting imdb info from: {}'.format(id))

        response = False

        for i in range(0, 3):

            try:
                response = requests.get(f'https://imdb-lake-tate.appversion6.workers.dev/title/{id}/',
                                        headers={"User-Agent": "Mozilla/5.0"})

                if response.status_code == 200:
                    break
            except:

                print('Something went wrong in imdb get_info')

        if not response:
            return False

        soup = BeautifulSoup(response.text, "html.parser")

        json_data = json.loads(soup.find(id='__NEXT_DATA__').text)

        props = json_data['props']['pageProps']
        fold_data = {}

        if imdb.has_key(props, 'aboveTheFoldData'):
            fold_data = props['aboveTheFoldData']

        metacritic_rate = ''
        if imdb.has_key(fold_data, 'metacritic') and imdb.has_key(fold_data['metacritic'], 'metascore'):
            metacritic_rate = fold_data['metacritic']['metascore']['score']

        rank = ''
        if imdb.has_key(fold_data, 'meterRanking') and imdb.has_key(fold_data['meterRanking'], 'currentRank'):
            rank = fold_data['meterRanking']['currentRank']

        age = ''
        if imdb.has_key(fold_data, 'certificate') and imdb.has_key(fold_data['certificate'], 'rating'):
            age = fold_data['certificate']['rating']

        awards = ''
        if kwargs.get('disable_translate') is None or kwargs.get('disable_translate') is False:
            if soup.find(attrs={'data-testid': 'award_information'}):
                awards = soup.find(attrs={'data-testid': 'award_information'}).text
                translate_text = GoogleTranslate.translate('en', 'fa', awards)

                if translate_text:
                    awards = translate_text

        genres = []
        if imdb.has_key(fold_data, 'genres'):
            for genre in fold_data['genres']['genres']:
                genres.append(imdb.translate_genres(genre['text']))

        directors = []
        if imdb.has_key(fold_data, 'directorsPageTitle'):
            for item in fold_data['directorsPageTitle']:

                for director in item['credits']:
                    directors.append(director['name']['nameText']['text'])

        actors = []
        if kwargs.get('disable_actors') is None or kwargs.get('disable_actors') is False:

            if 'cast' in props['mainColumnData']:

                for actor in props['mainColumnData']['cast']['edges']:
                    person = imdb.get_person_info(actor['node']['name']['id'])

                    if not person:
                        continue

                    actors.append(person)

        image = ''

        if imdb.has_key(fold_data, 'primaryImage') and imdb.has_key(fold_data['primaryImage'], 'url'):
            image = fold_data['primaryImage']['url']

        runtime = ''
        if imdb.has_key(fold_data, 'runtime') and imdb.has_key(fold_data['runtime'], 'seconds'):
            runtime = int(fold_data['runtime']['seconds']) / 60

        summary = ''
        if imdb.has_key(fold_data, 'plot') and imdb.has_key(fold_data['plot'], 'plotText'):
            if imdb.has_key(fold_data['plot']['plotText'], 'plainText'):
                summary = fold_data['plot']['plotText']['plainText']

        votes = ''
        if imdb.has_key(fold_data, 'ratingsSummary') and imdb.has_key(fold_data['ratingsSummary'], 'voteCount'):
            votes = fold_data['ratingsSummary']['voteCount']

        rating = ''
        if imdb.has_key(fold_data, 'ratingsSummary') and imdb.has_key(fold_data['ratingsSummary'], 'aggregateRating'):
            rating = fold_data['ratingsSummary']['aggregateRating']

        release = ''
        if imdb.has_key(fold_data, 'releaseYear') and imdb.has_key(fold_data['releaseYear'], 'year'):
            release = fold_data['releaseYear']['year']

        trailer = ''
        if imdb.has_key(fold_data, 'primaryVideos') and imdb.has_key(fold_data['primaryVideos'], 'edges'):

            for edge in fold_data['primaryVideos']['edges']:
                plays = edge['node']['playbackURLs']

                for video in plays:

                    if video['videoDefinition'] == 'DEF_480p':
                        trailer = video['url']

                if not trailer:

                    for video in plays:
                        trailer = video['url']

                        break

        type = 'movies'

        if fold_data['titleType']['isSeries']:
            type = 'series'

        return {
            'imdb_id': json_data['props']['pageProps']['tconst'],
            'type': type,
            'title': fold_data['titleText']['text'],
            'release': release,
            'genres': genres,
            'directors': directors,
            'actors': actors,
            'rating': rating,
            'votes': votes,
            'summary': summary,
            'runtime': runtime,
            'image': image,
            'rank': rank,
            'metacritic_rate': metacritic_rate,
            'age': age,
            'awards': awards,
            'trailer': trailer,
        }

    @staticmethod
    def get_person_info(id):

        response = False

        for i in range(0, 3):

            try:
                response = requests.get(f'https://imdb-lake-tate.appversion6.workers.dev/name/{id}/',
                                        headers={"User-Agent": "Mozilla/5.0"})

                if response.status_code == 200:
                    break
            except:

                print('Something went wrong in get_person_info method')

        if not response:
            return False

        soup = BeautifulSoup(response.text, "html.parser")

        json_data = json.loads(soup.find(id='__NEXT_DATA__').text)

        name = ''
        if json_data['props']['pageProps']['aboveTheFold']['nameText']:
            name = json_data['props']['pageProps']['aboveTheFold']['nameText']['text']

        image = ''
        if json_data['props']['pageProps']['aboveTheFold']['primaryImage']:
            image = json_data['props']['pageProps']['aboveTheFold']['primaryImage']['url']

        bio = ''
        if json_data['props']['pageProps']['aboveTheFold']['bio']:
            bio = json_data['props']['pageProps']['aboveTheFold']['bio']['text']['plainText']

        birth_date = ''
        if json_data['props']['pageProps']['aboveTheFold']['birthDate']:
            birth_date = json_data['props']['pageProps']['aboveTheFold']['birthDate']['date']

        birth_location = ''
        if json_data['props']['pageProps']['mainColumnData']['birthLocation']:
            birth_location = json_data['props']['pageProps']['mainColumnData']['birthLocation']['text']

        return {
            'id': id,
            'name': name,
            'image': image,
            'birth_date': birth_date,
            'birth_location': birth_location,
            'bio': bio,
        }

    @staticmethod
    def find_id_by_title(title):

        response = False
        
        print(f'https://imdb-lake-tate.appversion6.workers.dev/find/?q={title}&s=tt&ref_=fn_ttl_ex')

        for i in range(0, 3):

            try:
                response = requests.get(
                    f'https://imdb-lake-tate.appversion6.workers.dev/find/?q={title}&s=tt&ref_=fn_ttl_ex',
                    headers={"User-Agent": "Mozilla/5.0"})

                if response.status_code == 200:
                    break
            except:

                print('Something went wrong in find_id_by_title method')

        if not response:
            return False

        soup = BeautifulSoup(response.text, 'html.parser')

        json_data = json.loads(soup.find(id='__NEXT_DATA__').text)

        if json_data['props']['pageProps']['titleResults']['hasExactMatches']:

            response = False

            for i in range(0, 3):

                try:
                    response = requests.get(
                        f'https://imdb-lake-tate.appversion6.workers.dev/find/?q={title}&s=tt&exact=true&ref_=fn_ttl_ex',
                        headers={"User-Agent": "Mozilla/5.0"})

                    if response.status_code == 200:
                        break
                except:

                    print('Something went wrong in find_id_by_title method')

            if not response:
                return False

            soup = BeautifulSoup(response.text, 'html.parser')

            json_data = json.loads(soup.find(id='__NEXT_DATA__').text)

            if json_data['props']['pageProps']['titleResults']['results']:
                return json_data['props']['pageProps']['titleResults']['results'][0]['index']

        else:

            if json_data['props']['pageProps']['titleResults']['results']:
                return json_data['props']['pageProps']['titleResults']['results'][0]['index']

        return False

    def translate_genres(this_genres):
        genres = {
            'Action': 'اکشن',
            'Adventure': 'ماجراجویی',
            'Animation': 'انیمیشن',
            'Biography': 'بیوگرافی',
            'Comedy': 'کمدی',
            'Crime': 'جنایی',
            'Documentary': 'مستند',
            'Drama': 'درام',
            'Family': 'خانوادگی',
            'Fantasy': 'فانتزی',
            'Film Noir': 'فیلم نوآر',
            'History': 'تاریخی',
            'Horror': 'ترسناک',
            'Music': 'آهنگ',
            'Musical': 'موزیکال',
            'Mystery': 'رازآلود',
            'Romance': 'عاشقانه',
            'Sci-Fi': 'علمی تخیلی',
            'Short': 'کوتاه',
            'Sport': 'ورزشی',
            'Superhero': 'ابرقهرمانی',
            'Thriller': 'هیجان انگیز',
            'War': 'جنگی',
            'Western': 'وسترن',
            'Talk Show': 'تاک شو',
            'Sitcom': 'کمدی موقعیت',
            'Film-Noir': 'فیلم نوآر',
            'reality-tv': 'تلویزیون واقع‌نما',
            'Reality-TV': 'تلویزیون واقع‌نما',
            'Game-Show': 'مسابقه تلویزیونی',
            'Talk-Show': 'تاک شو',
            'News': 'اخبار',
            'Shounen': 'شومن',
            'Childcare': 'کودک',
            'Supernatural': 'ماوراء الطبیعه',
            'Gore': 'گور',
        }
        return genres.get(this_genres, this_genres)
