<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def action(self, action, movie=None, show=None, episode=None, progress=0.0, **kwargs):
 """Perform scrobble action. :param action: Action to perform (either :code:`start`, :code:`pause` or :code:`stop`) :type action: :class:`~python:str` :param movie: Movie definition (or `None`) **Example:** .. code-block:: python { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'tmdb': 118340 } } :type movie: :class:`~python:dict` :param show: Show definition (or `None`) **Example:** .. code-block:: python { 'title': 'Breaking Bad', 'year': 2008, 'ids': { 'tvdb': 81189 } } :type show: :class:`~python:dict` :param episode: Episode definition (or `None`) **Example:** .. code-block:: python { "season": 3, "number": 11 } :type episode: :class:`~python:dict` :param progress: Current movie/episode progress percentage :type progress: :class:`~python:float` :param kwargs: Extra request options :type kwargs: :class:`~python:dict` :return: Response (or `None`) **Example:** .. code-block:: python { 'action': 'start', 'progress': 1.25, 'sharing': { 'facebook': true, 'twitter': true, 'tumblr': false }, 'movie': { 'title': 'Guardians of the Galaxy', 'year': 2014, 'ids': { 'trakt': 28, 'slug': 'guardians-of-the-galaxy-2014', 'imdb': 'tt2015381', 'tmdb': 118340 } } } :rtype: :class:`~python:dict` """

        if movie and (show or episode):
            raise ValueError('Only one media type should be provided')

        if not movie and not episode:
            raise ValueError('Missing media item')

        data = {
            'progress': progress,
            'app_version': kwargs.pop('app_version', self.client.version),
            'app_date': kwargs.pop('app_date', None)
        }

        if movie:
            # TODO validate
            data['movie'] = movie
        elif episode:
            if show:
                data['show'] = show

            # TODO validate
            data['episode'] = episode

        response = self.http.post(
            action,
            data=data,
            **popitems(kwargs, [
                'authenticated',
                'validate_token'
            ])
        )

        return self.get_data(response, **kwargs)