# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
    clean_html,
    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,
            "Downloading %s JSON metadata" % resource,
            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,
                }
            )
        self._sort_formats(formats)

        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, compat_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.geturl()

        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": "https://www.minds.com/" + uploader_id
            if uploader_id
            else None,
            "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(
                "v2/feeds/container/%s/videos" % feed_id, feed_id, "page %s" % 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(
            "v1/%s/%s" % (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,
    }
