text: # -*- coding: utf-8 -*-
  from __future__ import absolute_import, unicode_literals
  
  import re
  
  from dateutil.parser import parse
  
  from .imdbpie import Imdb
  from .objects import (
      Title, TitleEpisodes, Name, TitleName, Image, TitleRelease,
      TitleSearchResult, NameSearchResult,
  )
  
  REGEX_IMDB_ID = re.compile(r'([a-zA-Z]{2}[0-9]{7})')
  
  
  class ImdbFacade(object):
  
      def __init__(self, client=None):
          self._client = client or Imdb()
  
      def get_title(self, imdb_id):
          title_data, title_aux_data = self._get_title_data(imdb_id=imdb_id)
          try:
              runtime = title_aux_data['runningTimes'][0]['timeMinutes']
          except (KeyError, IndexError):
              runtime = None
          try:
              episodes = TitleEpisodes(facade=self, imdb_id=imdb_id)
          except LookupError:
              episodes = ()
          try:
              season = title_aux_data['season']
              episode = title_aux_data['episode']
          except KeyError:
              season = None
              episode = None
          return Title(
              season=season, episode=episode, episodes=episodes,
              runtime=runtime, **title_data
          )
  
      def get_name(self, imdb_id):
          name_data = self._client.get_name(imdb_id=imdb_id)
          name = name_data['base']['name']
          imdb_id = self._parse_id(name_data['base']['id'])
  
          try:
              image_data = name_data['base']['image']
              image = Image(
                  url=image_data['url'],
                  height=image_data['height'],
                  width=image_data['width'],
              )
          except KeyError:
              image = None
  
          gender = name_data['base']['gender'].lower()
          date_of_birth = parse(name_data['base']['birthDate']).date()
          birth_place = name_data['base']['birthPlace']
          try:
              bios = tuple(b['text'] for b in name_data['base']['miniBios'])
          except KeyError:
              bios = ()
  
          filmography_data = self._client.get_name_filmography(imdb_id)
          filmography = tuple(
              self._parse_id(f['id']) for f in filmography_data['filmography']
          )
          return Name(
              name=name, imdb_id=imdb_id, date_of_birth=date_of_birth,
              gender=gender, birth_place=birth_place, bios=bios, image=image,
              filmography=filmography,
          )
  
      def search_for_name(self, query):
          results = []
          for result in self._client.search_for_name(query):
              result = NameSearchResult(
                  imdb_id=result['imdb_id'], name=result['name'],
              )
              results.append(result)
          return tuple(results)
  
      def search_for_title(self, query):
          results = []
          for result in self._client.search_for_title(query):
              if result['year']:
                  year = int(result['year'])
              else:
                  year = None
              result = TitleSearchResult(
                  imdb_id=result['imdb_id'], title=result['title'],
                  type=result['type'], year=year,
              )
              results.append(result)
          return tuple(results)
  
      def _get_writers(self, top_crew_data):
          return tuple(
              TitleName(
                  name=i['name'],
                  job=i.get('job'),
                  category=i.get('category'),
                  imdb_id=self._parse_id(i['id'])
              ) for i in top_crew_data['writers']
          )
  
      def _get_stars(self, principals_data):
          return tuple(
              TitleName(
                  name=i['name'],
                  job=i.get('job'),
                  characters=tuple(i.get('characters', ())),
                  category=i.get('category'),
                  imdb_id=self._parse_id(i['id'])
              ) for i in principals_data
          )
  
      def _get_creators(self, top_crew_data):
          return tuple(
              TitleName(
                  name=i['name'],
                  job=i.get('job'),
                  category=i.get('category'),
                  imdb_id=self._parse_id(i['id'])
              ) for i in top_crew_data['writers']
              if i.get('job') == 'creator'
          )
  
      def _get_directors(self, top_crew_data):
          return tuple(
              TitleName(
                  name=i['name'],
                  job=i.get('job'),
                  category=i.get('category'),
                  imdb_id=self._parse_id(i['id'])
              ) for i in top_crew_data['directors']
          )
  
      def _get_credits(self, credits_data):
          credits = []
          for category in credits_data.get('credits', ()):
              for item in credits_data['credits'][category]:
                  credits.append(TitleName(
                      name=item['name'],
                      category=item.get('category'),
                      job=item.get('job'),
                      imdb_id=self._parse_id(item['id'])
                  ))
          return tuple(credits)
  
      def _parse_id(self, string):
          return REGEX_IMDB_ID.findall(string)[0]
  
      def _get_title_data(self, imdb_id):
          base_title_data = self._client.get_title(imdb_id=imdb_id)
          top_crew_data = self._client.get_title_top_crew(imdb_id=imdb_id)
          title_aux_data = self._client.get_title_auxiliary(imdb_id=imdb_id)
          credits_data = self._client.get_title_credits(imdb_id=imdb_id)
  
          title = base_title_data['base']['title']
          year = base_title_data['base'].get('year')
          try:
              rating = float(base_title_data['ratings']['rating'])
          except KeyError:
              rating = None
          type_ = base_title_data['base']['titleType'].lower()
  
          try:
              releases_data = self._client.get_title_releases(imdb_id=imdb_id)
          except LookupError:
              release_date = None
              releases = ()
          else:
              release_date = parse(releases_data['releases'][0]['date']).date()
              releases = tuple(
                  TitleRelease(date=parse(r['date']).date(), region=r['region'])
                  for r in releases_data['releases']
              )
  
          try:
              rating_count = base_title_data['ratings']['ratingCount']
          except KeyError:
              rating_count = 0
  
          try:
              plot_outline = base_title_data['plot']['outline']['text']
          except KeyError:
              plot_outline = None
  
          writers = self._get_writers(top_crew_data)
          directors = self._get_directors(top_crew_data)
          creators = self._get_creators(top_crew_data)
          try:
              genres = tuple(g.lower() for g in title_aux_data.get('genres'))
          except TypeError:
              genres = ()
          credits = self._get_credits(credits_data)
  
          try:
              certification = title_aux_data['certificate']['certificate']
          except TypeError:
              certification = None
          stars = self._get_stars(title_aux_data['principals'])
          try:
              image_data = title_aux_data['image']
              image = Image(
                  url=image_data['url'],
                  height=image_data['height'],
                  width=image_data['width'],
              )
          except KeyError:
              image = None
          return dict(
              imdb_id=imdb_id,
              title=title,
              year=year,
              rating=rating,
              type=type_,
              release_date=release_date,
              releases=releases,
              plot_outline=plot_outline,
              rating_count=rating_count,
              writers=writers,
              directors=directors,
              creators=creators,
              genres=genres,
              credits=credits,
              certification=certification,
              image=image,
              stars=stars,
          ), title_aux_data
  