# -*- coding: UTF-8 -*-

# Copyright (©) 2005-2025 V.Nunes, P. Ożarowski, A. Flöter, W. Friebel
#
# 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 2 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 Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

# You may use and distribute this software under the terms of the
# GNU General Public License, version 2 or later

"""Note: This plugin will likely need to be updated once the imdb.com decides to
change the generated web page it provides.

Current state is 2026-02-24.
"""

import gutils
import movie
import re
from gettext import gettext as _
from bs4 import BeautifulSoup
from dataclasses import dataclass
import logging
import requests

# from movie import create_tempfile

log = logging.getLogger('Griffith')

plugin_name = 'IMDb'
plugin_description = 'Internet Movie Database'
plugin_url = 'www.imdb.com'
plugin_language = _('English')
plugin_author = 'Vasco Nunes, Piotr Ożarowski, Andreas Flöter, W. Friebel'
plugin_author_email = 'wp.friebel@gmail.com'
plugin_version = '1.22'


def before_more(data):
    for element in ['>See more<', '>more<', '>Full summary<', '>Full synopsis<']:
        tmp = data.find(element)
        if tmp > 0:
            data = data[:tmp] + '>'
    return data


def read_page(filename):
    with open(filename, 'r') as fp:
        return fp.read()


def is_genres_span(tag):
    return tag.name == 'span' and tag.text.strip() == 'Genres'


def is_director_span(tag):
    return tag.name == 'span' and tag.text.strip() == 'Director'


def is_language_tag(tag):
    # if tag.name == 'a' and '/search/title?title_type=feature&primary_language' in tag['href']:
    #     print(f"tag.name={tag.name}, tag['href']={tag['href']}")
    return tag.name == 'a' and '/search/title?title_type=feature&primary_language' in tag['href']


def is_mediaviewer_tag(tag):
    if tag.name == 'a' and 'mediaviewer' in tag['href']:
        log.debug(f"tag.name={tag.name}, tag['href']={tag['href']}")
    return tag.name == 'a' and 'mediaviewer' in tag['href']


def is_storyline_tag(tag):
    # <li class="ipc-metadata-list__item ipc-metadata-list-item--link" data-test
    # id="storyline-certificate" role="presentation">
    # if (tag.name == 'li' and 'data-testid' in tag.attrs.keys()
    #         and 'storyline-certificate' in tag.attrs['data-testid']):
    #     print(f"tag.name={tag.name} {tag.attrs}")
    return (tag.name == 'li' and 'data-testid' in tag.attrs.keys()
            and 'storyline-certificate' in tag.attrs['data-testid'])


def is_studio_tag(tag):
    # <li role="presentation" class="ipc-metadata-list__item ipc-metadata-list-
    # item--link" data-testid="title-details-companies">
    # if tag.name == 'li' and 'data-testid' in tag.attrs.keys()
    #     and 'title-details-companies' in tag.attrs['data-testid']:
    #     print(f"tag.name={tag.name} {tag.attrs}")
    return (tag.name == 'li' and 'data-testid' in tag.attrs.keys()
            and 'title-details-companies' in tag.attrs['data-testid'])


def is_plot_tag(tag):
    return (tag.name == 'div' and 'data-testid' in tag.attrs.keys()
            and 'sub-section-summaries' in tag.attrs['data-testid'])


@dataclass
class MovieInfo:
    title: str
    movie_id: str
    extra_info: str


class Plugin(movie.Movie):
    def __init__(self, movie_id: int):
        self.page_main = None
        self.page_cast = None
        self.page_plot = None
        self.encode = 'utf-8'
        self.movie_id = movie_id
        # example: [Shakespeare in Love] main page
        #   https://www.imdb.com/de/title/tt0138097/?ref_=fn_t_1
        #   https://www.imdb.com/title/tt0138097/?ref_=fn_t_1
        # self.url = f"https://www.imdb.com/title/tt{self.movie_id}/" + r"(?ref_=tt_ov_i)?$')"
        # self.url = f"https://www.imdb.com/title/tt{self.movie_id}/(\?ref_=tt_ov_i)?$"
        self.url = f"https://www.imdb.com/title/tt{self.movie_id}/"
        self.soup = None
        self.soup_cast = None
        self.soup_plot = None
        log.debug(f"[Plugin>__init__] Movie Info: {movie_id}")

    def initialize(self):
        self.page_cast = self.open_page(url=self.url + 'fullcredits')
        self.page_main = self.open_page(url=self.url)
        self.page_plot = self.open_page(url=self.url + 'plotsummary')
        # self.comp_page = self.open_page(url=self.url + 'companycredits')
        # self.tagl_page = self.open_page(url=self.url + 'taglines')
        # self.cert_page = self.open_page(url=self.url + 'parentalguide')
        # self.release_page = self.open_page(url=self.url + 'releaseinfo')
        self.soup = BeautifulSoup(self.page_main, 'html.parser')
        self.soup_cast = BeautifulSoup(self.page_cast, 'html.parser')
        self.soup_plot = BeautifulSoup(self.page_plot, 'html.parser')

    def get_image(self):
        # example: [Shakespeare in Love] main page
        #   https://www.imdb.com/de/title/tt0138097/mediaviewer/rm3876398849/?ref_=tt_ov_i
        #   https://www.imdb.com/title/tt0138097/mediaviewer/rm3876398849/?ref_=tt_ov_i
        url_pattern = re.compile(r'^((https://www.imdb.com)?/title/tt\d+/'
                                 r'mediaviewer/rm\d+/)(\?ref_=tt_ov_i)?$')
        self.image_url = ''
        image_page_url = ''

        for tag in self.soup.find_all(is_mediaviewer_tag):
            match = url_pattern.match(tag['href'])
            if match:
                image_page_url_suffix = match.groups()[0]
                log.debug(f"URL candidate: {match.groups()[0]}")
                if match.groups()[2]:
                    if not match.groups()[1]:
                        image_page_url = \
                            f"https://www.imdb.com{image_page_url_suffix}"
                    log.debug(f"[PluginMovieIMDB>get_image]: Image Page URL: "
                              f"{image_page_url}")
                    break
                else:
                    log.debug(f"Not correct URL found: {match.groups()[0]}")
        image_page = requests.get(image_page_url,
                                  headers=self.config.http_header)
        if image_page.status_code != 200:
            log.debug(f"Unable to retrieve image page: {image_page_url}, "
                      f"code:{image_page.status_code}")
            return
        if image_page_url.endswith('/'):
            image_id = image_page_url.split('/')[-2]
        else:
            image_id = image_page_url.split('/')[-1]
        soup_image_page = BeautifulSoup(image_page.content, 'html.parser')
        log.debug(f"soup_image_page: {len(soup_image_page.body)}")
        # <img alt="Gwyneth Paltrow and Joseph Fiennes in Shakespeare in Love (1998)"
        # class="sc-7c0a9e7c-0 eWmrns" data-image-id="rm381097216-curr"
        # sizes="100vw" src="https://m.media-amazon.com/images/M/MV5BM2ZkNjM5M
        # jEtNTBlMC00OTI5LTgyYmEtZDljMzNmNzhiNzY0XkEyXkFqcGdeQXVyNDYyMDk5MTU@.
        # _V1_.jpg"
        image_url = soup_image_page.find(
            'img', {'data-image-id': f'{image_id}-curr'}).attrs['src']
        log.debug(f"image_url: {image_url}")
        # image = requests.get(image_url, headers=self.config.http_header)
        # log.debug(f"image: {len(image.content)}")
        # fd, filename = create_tempfile()
        # with open(filename, 'wb') as fp:
        #     fp.write(image.content)
        # self.image = filename
        self.image_url = image_url

    def get_o_title(self):
        self.o_title = gutils.trim(self.page_main, '<div class="originalTitle">', '<span')
        if not self.o_title:
            self.o_title = gutils.regextrim(self.page_main, '<h1 itemprop="name"[^>]*>', '&nbsp;')
        if not self.o_title:
            self.o_title = gutils.trim(self.page_main, 'og:title\' content="', '"')
        if not self.o_title:
            self.o_title = re.sub(' [(].*', '', gutils.trim(self.page_main, '<title>', '</title>'))
        self.o_title = gutils.clean(re.sub('"', '', self.o_title))

    def get_title(self):
        title_section = self.soup.find('h1', {'data-testid': 'hero__pageTitle'})
        if title_section:
            title = title_section.find('span', {'class': 'hero__primary-text'})
            if title:
                self.title = title.text.strip()
            else:
                self.title = ''

    def get_director(self):
        self.director = ''
        directors = []
        div_tag = None
        for tag in self.soup.find_all(is_director_span):
            div_tag = tag.next_sibling
            # log.debug(f"div_tag: {div_tag}")
            break
        if div_tag:
            for a_tag in div_tag.find_all(
                    'a',
                    {'class': 'ipc-metadata-list-item__list-content-item '
                              'ipc-metadata-list-item__list-content-item--link'}):
                directors.append(a_tag.text.strip())
            if directors:
                self.director = ', '.join(directors)

    def get_plot(self):
        self.plot = ''
        plot_summaries = []
        div_summaries_tag = self.soup_plot.find(is_plot_tag)
        if div_summaries_tag:
            for div_tag in div_summaries_tag.find_all(
                    'div',
                    {'class': 'ipc-html-content-inner-div'}):
                plot_summary = div_tag.find('div', {'role': 'presentation'})
                if not plot_summary:
                    continue
                plot_summary = plot_summary.text.strip()
                plot_summary = plot_summary.replace(r"\n", ' ')
                pos_author = plot_summary.find('—')
                log.debug(f"plot_summary: {plot_summary} pos_author: {pos_author}")
                if pos_author > 0:
                    plot_summary = plot_summary[:pos_author]
                a_author_tag = div_tag.find('a', {'class': 'ipc-link ipc-link--base'})
                if a_author_tag:
                    author = a_author_tag.text.strip()
                    plot_summaries.append(f"{plot_summary}\nAuthor: {author}")
                    log.debug(f"{plot_summary}\nAuthor: {author}")
                else:
                    log.debug("No author 'a' tag found")
                    plot_summaries.append(f"{plot_summary}")
                    log.debug(f"{plot_summary}")
            self.plot = '\n\n'.join(plot_summaries)

    def get_year(self):
        self.year = gutils.trim(self.page_main, '<a href="/year/', '</a>')
        self.year = gutils.after(self.year, '>')
        if not self.year:
            tmp = gutils.trim(self.page_main, '<title>', '</title>')
            tmp = re.search('([0-9]{4})', tmp)
            if tmp:
                self.year = tmp.group(0)

    def get_runtime(self):
        # runtime_hm_pattern = re.compile(r'(\d+).*hour\D+(\d+)\D+minutes')
        # runtime_h_pattern = re.compile(r'(\d+).*hour\D*')
        runtime_min_pattern = re.compile(r'.*\((\d+) min\).*')
        hours, minutes = 0, 0

        # <li role="presentation" class="ipc-metadata-list__item ipc-metadata-li
        # st__item--align-end" data-testid="title-techspec_runtime">
        tec_section = self.soup.find('div', {'data-testid': 'title-techspecs-section'})
        log.debug(f"__ tec_section:\n{tec_section}")
        if tec_section:
            # <div class="ipc-metadata-list-item__content-container">1<!-- -->
            # <!-- -->hour<!-- --> <!-- -->55<!-- --> <!-- -->minutes</div>
            tec_topic = tec_section.find(
                'span',
                {'class': 'ipc-metadata-list-item__list-content-item--subText'})
            if tec_topic:
                log.debug(f"tec_topic:\n{tec_topic} text: {tec_topic.text}")
                match = runtime_min_pattern.match(tec_topic.text)
                if match:
                    minutes = int(match.groups()[0])
        self.runtime = minutes

    def get_genre(self) -> None:
        self.genre = ''
        # e.g. "genre":["Comedy","Crime","Drama"]
        # pattern = re.compile('^.+"genre":\[([^]]+)].+$', re.DOTALL)
        pattern = re.compile(r'^.*"genre":\[([^]]+)].*$', re.DOTALL)
        match = pattern.match(self.page)
        if match:
            genres = match.groups()[0]
            genres = genres.replace('"', '')
            genres = ', '.join(genres.split(','))
            self.genre = genres

    def get_cast(self):
        """Search and retrieve from the self.page_cast"""

        # example element
        # <ul class="ipc-metadata-list ipc-metadata-list--dividers-none sc-9e1b1
        # f-0 eHlCSc meta-data-list-full full-credits-page-list ipc-metadata-lis
        # t--base" role="presentation">
        cast_section = self.soup_cast.find_all(
            'ul', {'class': 'full-credits-page-list'})[2]
        # example element
        # <a class="ipc-link ipc-link--base name-credits--title-text name-credit
        # s--title-text-small" tabindex="0" aria-disabled="false" href="/de/name
        # /nm0001691/?ref_=ttfc_fcr_3_1">Geoffrey Rush</a>
        casts = cast_section.find_all('a', {'class': 'name-credits--title-text-small'})
        cast_list = []
        for cast in casts:
            cast_list.append(cast.text.strip())
        if cast_list:
            self.cast = '\n'.join(cast_list)
        else:
            self.cast = ''

    def get_classification(self):
        """
        The classification is now extracted from the main page.
        """
        self.classification = ''
        pattern = r'<a class=".*/parentalguide/.*certificates">(\d+)</a>'
        res = re.search(pattern, self.page_main)
        if res.groups():
            self.classification = res.groups()[0]

    def get_studio(self):
        studio_list = []
        self.studio = ''
        studio_tag = self.soup.find(is_studio_tag)
        if studio_tag:
            studios = studio_tag.find_all(
                'a',
                {'class': "ipc-metadata-list-item__list-content-item "
                          "ipc-metadata-list-item__list-content-item--link"})
            for studio in studios:
                # print(f"studio.text={studio.text}")
                if studio.text.strip():
                    studio_list.append(studio.text.strip())
        self.studio = ', '.join(studio_list)

    def get_o_site(self):
        self.o_site = ''

    def get_site(self):
        self.site = f"https://www.imdb.com/title/tt{self.movie_id}/"

    def get_trailer(self):
        """
        Sets the trailer URL but does not check if actually trailers exist.
        """
        self.trailer = f"https://www.imdb.com/title/tt{self.movie_id}/trailers"

    def get_country(self):
        """not used"""
        self.country = gutils.after(gutils.trim(self.page_main, 'country_of_origin', '</a>'), '>')

    def get_rating(self):
        rating = gutils.strip_tags(gutils.trim(self.page_main, 'IMDb RATING', '</span>'))
        if rating:
            try:
                # self.rating = round(float(rating), 0)
                self.rating = float(rating)
            except ValueError as _exc:
                self.rating = 0
        else:
            self.rating = 0

    def get_notes(self):
        self.notes = ''
        color_value = ''
        sound_value = []
        language_value = ''

        a_language_tag = self.soup.find(is_language_tag)
        if a_language_tag:
            language_value = a_language_tag.text
        language = language_value

        # <div data-testid="title-techspecs-section" class="sc-f65f65be-0 bBlII">
        tec_section = self.soup.find('div', {'data-testid': 'title-techspecs-section'})
        # print(f"\ntec_section:\n{tec_section}")
        if tec_section:
            # <a aria-disabled="false" class="ipc-metadata-list-item__list-conte
            # nt-item ipc-metadata-list-item__list-content-item--link" href="/se
            # arch/title/?colors=color&amp;ref_=tt_spec_att" role="button" tabin
            # dex="0">Color</a>
            a_tags = tec_section.find_all(
                'a', {'class': r'ipc-metadata-list-item__list-content-item ipc-'
                               r'metadata-list-item__list-content-item--link'})
            for a_tag in a_tags:
                if 'colors=' in a_tag['href']:
                    # href="/search/title/?colors=color&ref_=tt_spec_att"
                    color_value = a_tag.text.strip()
                if 'sound_mixes=' in a_tag['href']:
                    # href="/search/title/?sound_mixes=stereo&ref_=tt_spec_att"
                    sound_value.append(a_tag.text.strip())
        color = color_value
        sound = ', '.join(sound_value)

        tagline = ''
        note_list = []
        if len(language) > 0:
            note_list.append("%s: %s" % (_('Language'), language))
        if len(sound) > 0:
            note_list.append("%s: %s" % (gutils.strip_tags(_('<b>Audio</b>')), sound))
        if len(color) > 0:
            note_list.append("%s: %s" % (_('Color'), color))
        if len(tagline) > 0:
            note_list.append("%s: %s" % ('Tagline', tagline))
        self.notes = '\n'.join(note_list)

    def get_screenplay(self):
        self.screenplay = ''
        cast_first_li = self.soup_cast.find(
            'li', {'class': 'name-credits--writer-family-fist-item'})
        log.debug(f"cast_first_li={cast_first_li}")
        screen_writers = []
        try:
            cast_div = cast_first_li.parent.parent
            # log.debug(f"cast_div={cast_div}")
            for li_elem in cast_div.find_all('li'):
                screenplay_writer = li_elem.div.div.div.div.a.text.strip()
                # log.debug(f"screenplay_writer: {screenplay_writer}")
                screen_writers.append(screenplay_writer)
        except AttributeError as exc:
            log.debug(f"Couldn't find cast first <li> tag for movie: "
                      f"{self.movie_id}, {exc}")
        self.screenplay = ', '.join(screen_writers)

    def get_cameraman(self):
        """not used"""
        self.cameraman = ''
        # tmp = gutils.regextrim(self.page_cast, '>Cinematography by', '</table>')
        # tmp = tmp.split('href="')
        # if len(tmp) > 1:
        #     for entry in tmp[1:]:
        #         entry = gutils.trim(entry, '>', '<')
        #         entry = entry.replace('\n', '')
        #         entry = entry.strip()
        #         if entry:
        #             self.cameraman = self.cameraman + entry + ', '
        #     if self.cameraman:
        #         self.cameraman = self.cameraman[:-2]


class SearchPlugin(movie.SearchMovie):

    def __init__(self):
        """
        https://www.imdb.com/find?s=tt;q=
        Seems to give the best results. 25 results for "Damages", popular titles
        first.
        """
        super().__init__()
        self.original_url_search = 'https://www.imdb.com/find?s=tt&q='
        self.translated_url_search = 'https://www.imdb.com/find?s=tt&q='
        self.encode = 'utf8'
        self.page = None
        log.debug(f"[SearchPlugin>__init__] {self.original_url_search}")

    def search(self, parent_window):
        if not self.open_search(parent_window):
            return None
        return self.page

    def get_searches(self):
        # movie_id_pattern = re.compile(r'/title/tt(\d+).*$')
        movie_id_pattern = re.compile(r'/title/tt(\d+)/\?ref_=fn_.*$')
        # log.debug(f"[SearchPlugin>get_searches] {self.page}")
        soup = BeautifulSoup(self.page, 'html.parser')
        # example tag for a search result
        '''<div class="ipc-title ipc-title--base ipc-title--title ipc-title-link
-no-icon ipc-title--on-textPrimary sc-87337ed2-2 dRlLYG cli-title with-margin"><
a href="/de/title/tt0138097/?ref_=fn_t_1" class="ipc-title-link-wrapper" tabinde
x="0"><h3 class="ipc-title__text">Shakespeare in Love</h3></a></div>'''
        movie_div_items = soup.find_all(
            'div',
            {'class': 'ipc-title--title'})
        for movie_item in movie_div_items:
            # <div class="ipc-metadata-list-summary-item__tc">
            movie_entry = movie_item.find(
                'a', {'class': 'ipc-title-link-wrapper'})
            # movie_entry = movie_item.find(
            #     'h3', {'class': 'ipc-title__text'})
            if movie_entry is None:
                continue
            else:
                movie_title = movie_entry.text.strip()
            movie_id_element = movie_entry['href']
            match = movie_id_pattern.match(movie_id_element)
            if match:
                movie_id = match.groups()[0]
            else:
                movie_id = ''
            # <li role="presentation" class="ipc-inline-list__item">
            movie_additional_infos = movie_item.find_all(
                'li', {'class': 'ipc-inline-list__item'})
            infos = []
            for additional_info in movie_additional_infos:
                # <span class="ipc-metadata-list-summary-item__li" aria-disabled="false">
                info = additional_info.find(
                    'span', {'class': 'ipc-metadata-list-summary-item__li'})
                if info:
                    infos.append(info.text)
            movie_info = MovieInfo(movie_title, movie_id, '|'.join(infos))
            self.ids.append(movie_info.movie_id)
            if movie_info.extra_info:
                self.titles.append(
                    ' - '.join((movie_info.title, movie_info.extra_info)))
            else:
                self.titles.append(movie_info.title)


class SearchPluginTest(SearchPlugin):
    """
    Plugin test for the search plugin
    Configuration for automated tests:
    dict { movie_id -> [ expected result count for original url,
                         expected result count for translated url ] }
    """
    test_configuration = {
        'Damages': [25, 25],
        'Ein glückliches Jahr': [17, 17],
        'Shakespeare in Love': [20, 20],
        }


class PluginTest:
    """
    Plugin test for the extraction of content for a film
    Configuration for automated tests:
    dict { movie_id -> dict { arribute -> value } }

    value: * True/False if attribute only should be tested for any value
           * or the expected value
    """
    test_configuration = {
        '0138097': {
            'year': 1998,
            'runtime': 123,
            'cast': '''Geoffrey Rush
    Tom Wilkinson
    Steven O'Donnell
    Tim McMullan
    Joseph Fiennes
    Steven Beard
    Antony Sher
    Patrick Barlow
    Martin Clunes
    Sandra Reinton
    Simon Callow
    Judi Dench
    Bridget McConnell
    Georgie Glen
    Nicholas Boulton
    Gwyneth Paltrow
    Imelda Staunton
    Colin Firth
    Desmond McNamara
    Barnaby Kay
    Jim Carter
    Paul Bigley
    Jason Round
    Rupert Farley
    Adam Barker
    Joe Roberts
    Harry Gostelow
    Alan Cody
    Mark Williams
    David Curtiz
    Gregor Truter
    Simon Day
    Jill Baker
    Amber Glossop
    Robin Davies
    Hywel Simons
    Nicholas Le Prevost
    Ben Affleck
    Timothy Kightley
    Mark Saban
    Bob Barrett
    Roger Morlidge
    Daniel Brocklebank
    Roger Frost
    Rebecca Charles
    Richard Gold
    Rachel Clarke
    Lucy Speed
    Patricia Potter
    John Ramm
    Martin Neely
    The Choir of St. George's School in Windsor''',
            'plot': '''History's greatest playwright is young, out of ideas and shortof cash, but meets his ideal woman 
and is inspired to write one of his most famous plays.

    William Shakespeare (Joseph Fiennes) is a known but struggling poet, playwright, and actor, who has not only sold 
his next play to both Philip Henslowe (Geoffrey Rush) and Richard Burbage (Martin Clunes), but now faces a far more 
difficult problem: he is bereft of ideas and has yet to begin writing. He is in search of his muse, the woman who will 
inspire him, but all attempts fail him until he meets beautiful Viola De Lesseps (Gwyneth Paltrow). She loves the 
theatre and would like nothing more than to take to the stage, but is forbidden to do so as only men can be actors. She
 is also a great admirer of Shakespeare's works. Dressing as a man and going by the name of "Thomas Kent", she auditions
and is ideal for a part in his next play. Shakespeare soon sees through her disguise and they begin a love affair, one 
they know cannot end happily for them as he is already married and she has been promised to dour Lord Wessex 
(Colin Firth). As thecompany rehearses his new play, William and Viola's love is transferred to the written page, 
leading to the masterpiece that is "Romeo and Juliet".
    Author: garykmcd

    In 1593 London, Master William Shakespeare (Joseph Fiennes), an up-and-coming playwright and sonneteer, is not 
nearly as well-known as his counterpart, Christopher Marlowe (Rupert Everett), so William's current writer's block does 
not help him or the owner of the Rose Theatre, Philip Henslowe (Geoffrey Rush), for whom Will generally writes his 
plays--whenthe plague, or Henslowe's financial problems, has not closed the theater. That current unwritten play 
commissioned is a comedy tentatively titled "Romeo and Ethel, the Pirate's Daughter". Will's block is partly due to the 
loss of his muse, his mistress, who he caught in bed with another man, he having a mistress. Will begins to write again,
 and passionately, when he falls in love with Viola De Lesseps (Gwyneth Paltrow), who comes from a well-respected, 
well-off family. Shakespeare also learns that Viola and Thomas Kent, the young man who recently joined the company of 
the Rose, are one and the same, Viola masquerading as a man to infiltrate the theater world, a domain purely for the 
male sex, as she is in love with the written word, especially Shakespeare's. She also falls in love with Shakespeare 
the man and Shakespearethe writer. Without telling Henslowe or egotistical actor Ned Alleyn (Ben Affleck), an 
egotistical actor, Will is realizing that the play is neither the comedy "Romeo and Ethel, the Pirate's Daughter" 
nor one called "Mercutio"--the name of Alleyn's character--but is morphing into a love story called "Romeo and Juliet", 
the love based on his mutual feelings for Viola. Beyond her continuing to masquerade as Thomas Kent, their own love 
story has a major obstacle in that sheis betrothed to Lord Wessex (Colin Firth), a man she detests and a union 
sanctioned by her merchant father and Queen Elizabeth (Dame Judi Dench) primarily for financial and business purposes. 
The mounting of the play, Viola and Will's personal love affair, and their professional collaboration as playwright 
Will Shakespeare and actor "Thomas Kent" are setagainst the cutthroat business side of 16th-century English show 
business.
    Author: Huggo

    Romantic comedy set in London in the late 16th century: Young playwright William Shakespeare (Joseph Fiennes) 
struggleswith his latest work "Romeo and Ethel the Pirate's Daughter". A great fan of Shakespeare's plays is wealthy 
young Viola De Lesseps (Gwyneth Paltrow), who is about to be married to cold-hearted Lord Wessex (Colin Firth), but 
constantly dreams of becoming an actress. Women were not allowed to act on stage at that time and female roles were 
played by men, but dressed as a lad, Viola successfully auditions for the part of Romeo. Soon she and William are 
caught up in a forbidden romance that provides rich inspiration for his play.
    Author: Armin Ortmann''',
            'notes': '''Audio: Dolby Digital, DTS, SDDS
    Color: Color''',
            'rating': 7,
            'resolution': False,
            'image': True,
            'image_url': 'https://m.media-amazon.com/images/M/MV5BYmM3MTllNzYtN'
                         '2MzNS00NWQwLTk0NTEtNjY1MmMwYjNkNTE5XkEyXkFqcGc@._V1_'
                         '.jpg',
            'director': 'John Madden',
            'country': 'United Kingdom',
            'genre': '''Comedy, Drama, History''',
            'classification': '6',
            'studio': '''Universal Pictures, Miramax, The Bedford Falls Company''',
            'o_site': False,
            'site': 'https://www.imdb.com/title/tt0138097/',
            'trailer': 'https://www.imdb.com/title/tt0138097/trailers',
            'screenplay': False,
            'cameraman': False,
            'barcode': False,
            },
        }
