def sync_bundles(self, delete_bundles=True, update_metadata=True, confirm_delete_fun=None, dry_run=False):

        self.dry_run = dry_run
        self.sync_stats.clear()

        if dry_run:
            self.log('-----------------------------------')
            self.log('DRY RUN - not modifying any bundles')
            self.log('-----------------------------------')

        self.log('Fetching bundles...')
        bundle_map = self._load_bundle_map()
        self.log('Fetching videos...')
        videos = self.bc_client.get_all_videos()

        self.log('Checking {0} videos...'.format(len(videos)))
        for video in videos:
            vid = video['id']
            bundle = bundle_map.get(vid)

            if bundle is None:
                # Create a bundle for the video
                self._create_bundle_for_video(video)

            elif update_metadata:
                # Update the metadata in the bundle for the video
                self._update_metadata_for_video(get_link_href(bundle, 'clarify:metadata'), video)

        if delete_bundles:
            self.log('Checking deleted videos...')
            # Delete bundles for missing videos
            existing_vids = set([x['id'] for x in videos])
            existing_bundles = set(bundle_map.keys())
            missing_bundles = existing_bundles - existing_vids
            if len(missing_bundles):
                for vid in missing_bundles:
                    bundle = bundle_map.get(vid)
                    if dry_run or confirm_delete_fun is None or \
                            confirm_delete_fun(bundle['name'], bundle['external_id']):
                        self.log('Delete bundle for video {0}'.format(bundle['external_id']))
                        if not dry_run:
                            self.clarify_client.delete_bundle(get_link_href(bundle, 'self'))
                        self.sync_stats['deleted'] += 1

        self.sync_stats['count'] = len(bundle_map) + self.sync_stats['created'] - self.sync_stats['deleted']
        self.log('done.')
    def _load_bundle_map(self):
        '''
        Return a map of all bundles in the Clarify app that have an external_id set for them.
        The bundles with external_ids set are assumed to be the ones we have inserted from Brightcove.
        The external_id contains the Brightcove video id.
        '''
        bundle_map = {}
        next_href = None
        has_next = True

        while has_next:
            bundles = self.clarify_client.get_bundle_list(href=next_href, embed_items=True)
            items = get_embedded_items(bundles)
            for item in items:
                bc_video_id = item.get('external_id')
                if bc_video_id is not None and len(bc_video_id) > 0:
                    bundle_map[bc_video_id] = item
            next_href = get_link_href(bundles, 'next')
            if next_href is None:
                has_next = False
        return bundle_map