from .common import InfoExtractor
from ..utils import (
    clean_html,
    format_field,
    int_or_none,
    str_or_none,
    strip_or_none,
)


class MindsBaseIE(InfoExtractor):
    _VALID_URL_BASE = r'https?://(?:www\.)?minds\.com/'

    def _call_api(self, path, video_id, resource, query=None):
        api_url = 'https://www.minds.com/api/' + path
        token = self._get_cookies(api_url).get('XSRF-TOKEN')
        return self._download_json(
            api_url, video_id, f'Downloading {resource} JSON metadata', headers={
                'Referer': 'https://www.minds.com/',
                'X-XSRF-TOKEN': token.value if token else '',
            }, query=query)


class MindsIE(MindsBaseIE):
    IE_NAME = 'minds'
    _VALID_URL = MindsBaseIE._VALID_URL_BASE + r'(?:media|newsfeed|archive/view)/(?P<id>[0-9]+)'
    _TESTS = [{
        'url': 'https://www.minds.com/media/100000000000086822',
        'md5': '215a658184a419764852239d4970b045',
        'info_dict': {
            'id': '100000000000086822',
            'ext': 'mp4',
            'title': 'Minds intro sequence',
            'thumbnail': r're:https?://.+\.png',
            'uploader_id': 'ottman',
            'upload_date': '20130524',
            'timestamp': 1369404826,
            'uploader': 'Bill Ottman',
            'view_count': int,
            'like_count': int,
            'dislike_count': int,
            'tags': ['animation'],
            'comment_count': int,
            'license': 'attribution-cc',
        },
    }, {
        # entity.type == 'activity' and empty title
        'url': 'https://www.minds.com/newsfeed/798025111988506624',
        'md5': 'b2733a74af78d7fd3f541c4cbbaa5950',
        'info_dict': {
            'id': '798022190320226304',
            'ext': 'mp4',
            'title': '798022190320226304',
            'uploader': 'ColinFlaherty',
            'upload_date': '20180111',
            'timestamp': 1515639316,
            'uploader_id': 'ColinFlaherty',
        },
    }, {
        'url': 'https://www.minds.com/archive/view/715172106794442752',
        'only_matching': True,
    }, {
        # youtube perma_url
        'url': 'https://www.minds.com/newsfeed/1197131838022602752',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        entity_id = self._match_id(url)
        entity = self._call_api(
            'v1/entities/entity/' + entity_id, entity_id, 'entity')['entity']
        if entity.get('type') == 'activity':
            if entity.get('custom_type') == 'video':
                video_id = entity['entity_guid']
            else:
                return self.url_result(entity['perma_url'])
        else:
            assert entity['subtype'] == 'video'
            video_id = entity_id
        # 1080p and webm formats available only on the sources array
        video = self._call_api(
            'v2/media/video/' + video_id, video_id, 'video')

        formats = []
        for source in (video.get('sources') or []):
            src = source.get('src')
            if not src:
                continue
            formats.append({
                'format_id': source.get('label'),
                'height': int_or_none(source.get('size')),
                'url': src,
            })

        entity = video.get('entity') or entity
        owner = entity.get('ownerObj') or {}
        uploader_id = owner.get('username')

        tags = entity.get('tags')
        if tags and isinstance(tags, str):
            tags = [tags]

        thumbnail = None
        poster = video.get('poster') or entity.get('thumbnail_src')
        if poster:
            urlh = self._request_webpage(poster, video_id, fatal=False)
            if urlh:
                thumbnail = urlh.url

        return {
            'id': video_id,
            'title': entity.get('title') or video_id,
            'formats': formats,
            'description': clean_html(entity.get('description')) or None,
            'license': str_or_none(entity.get('license')),
            'timestamp': int_or_none(entity.get('time_created')),
            'uploader': strip_or_none(owner.get('name')),
            'uploader_id': uploader_id,
            'uploader_url': format_field(uploader_id, None, 'https://www.minds.com/%s'),
            'view_count': int_or_none(entity.get('play:count')),
            'like_count': int_or_none(entity.get('thumbs:up:count')),
            'dislike_count': int_or_none(entity.get('thumbs:down:count')),
            'tags': tags,
            'comment_count': int_or_none(entity.get('comments:count')),
            'thumbnail': thumbnail,
        }


class MindsFeedBaseIE(MindsBaseIE):
    _PAGE_SIZE = 150

    def _entries(self, feed_id):
        query = {'limit': self._PAGE_SIZE, 'sync': 1}
        i = 1
        while True:
            data = self._call_api(
                f'v2/feeds/container/{feed_id}/videos',
                feed_id, f'page {i}', query)
            entities = data.get('entities') or []
            for entity in entities:
                guid = entity.get('guid')
                if not guid:
                    continue
                yield self.url_result(
                    'https://www.minds.com/newsfeed/' + guid,
                    MindsIE.ie_key(), guid)
            query['from_timestamp'] = data['load-next']
            if not (query['from_timestamp'] and len(entities) == self._PAGE_SIZE):
                break
            i += 1

    def _real_extract(self, url):
        feed_id = self._match_id(url)
        feed = self._call_api(
            f'v1/{self._FEED_PATH}/{feed_id}',
            feed_id, self._FEED_TYPE)[self._FEED_TYPE]

        return self.playlist_result(
            self._entries(feed['guid']), feed_id,
            strip_or_none(feed.get('name')),
            feed.get('briefdescription'))


class MindsChannelIE(MindsFeedBaseIE):
    _FEED_TYPE = 'channel'
    IE_NAME = 'minds:' + _FEED_TYPE
    _VALID_URL = MindsBaseIE._VALID_URL_BASE + r'(?!(?:newsfeed|media|api|archive|groups)/)(?P<id>[^/?&#]+)'
    _FEED_PATH = 'channel'
    _TEST = {
        'url': 'https://www.minds.com/ottman',
        'info_dict': {
            'id': 'ottman',
            'title': 'Bill Ottman',
            'description': 'Co-creator & CEO @minds',
        },
        'playlist_mincount': 54,
    }


class MindsGroupIE(MindsFeedBaseIE):
    _FEED_TYPE = 'group'
    IE_NAME = 'minds:' + _FEED_TYPE
    _VALID_URL = MindsBaseIE._VALID_URL_BASE + r'groups/profile/(?P<id>[0-9]+)'
    _FEED_PATH = 'groups/group'
    _TEST = {
        'url': 'https://www.minds.com/groups/profile/785582576369672204/feed/videos',
        'info_dict': {
            'id': '785582576369672204',
            'title': 'Cooking Videos',
        },
        'playlist_mincount': 1,
    }