#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Bot to generate some video game statistics

Stolen from https://github.com/multichill/toollabs/blob/master/bot/wikidata/painting_property_statistics.py

These are published at https://www.wikidata.org/wiki/Wikidata:WikiProject_sum_of_all_paintings/Property_statistics

"""
import logging

import pywikibot
import pywikibot.data.sparql
import collections

class VideoGamePropertyStatistics:
    """
    Generate video games statitics

    """
    def __init__(self):
        """
        Set what to work on and other variables here.
        """
        site = pywikibot.Site('en', 'wikipedia')
        self.repo = site.data_repository()
        self.collection_threshold = 20
        self.property_threshold = 10
        self.targetPageTitle = u'Wikidata:WikiProject Video games/Statistics/Platform'
        self.properties = collections.OrderedDict()

        # Core properties
        self.properties[u'P136'] = u'[[Property:P136|genre]]'
        self.properties[u'P178'] = u'[[Property:P178|developer]]'
        self.properties[u'P123'] = u'[[Property:P123|publisher]]'
        self.properties[u'P495'] = u'[[Property:P495|country]]'
        self.properties[u'P577'] = u'[[Property:P577|publication date]]'
        
        # Gameplay properties
        self.properties[u'P404'] = u'[[Property:P404|game mode]]'

        self.properties[u'P437'] = u'[[Property:P437|distribution]]'

        # Staff properties
        self.properties[u'P57'] = u'[[Property:P57|director]]'
        self.properties[u'P287'] = u'[[Property:P287|designer]]'
        self.properties[u'P86'] = u'[[Property:P86|composer]]'
        self.properties[u'P162'] = u'[[Property:P162|producer]]'

        # Setting
        self.properties[u'P1434'] = u'[[Property:P1434|universe]]'
        self.properties[u'P840'] = u'[[Property:P840|narrative location]]'
        self.properties[u'P2408'] = u'[[Property:P2408|narrative period]]'

        self.propertyData = {}

    def get_collection_information(self):
        """
        Get the information for a single platform.

        :return: Tuple of two (ordered) dictionaries: First with counts, second with country codes
        """
        query = """SELECT ?item (COUNT(?item) as ?count) WHERE {
  ?game wdt:P31/wdt:P279* wd:Q7889 .
  ?game wdt:P400 ?item .
} GROUP BY ?item
HAVING (?count > %s)
ORDER BY DESC(?count)
LIMIT 1000""" % (self.collection_threshold,)
        platform_counts = collections.OrderedDict()

        sq = pywikibot.data.sparql.SparqlQuery()
        queryresult = sq.select(query)

        for resultitem in queryresult:
            qid = resultitem.get('item').replace(u'http://www.wikidata.org/entity/', u'')
            platform_counts[qid] = int(resultitem.get('count'))
        return platform_counts

    def get_property_info(self, prop):
        """
        Get the usage counts for a property for the collections

        :param prop: Wikidata Pid of the property
        :return: (Ordered) dictionary with the counts per collection
        """
        query = """SELECT ?item (COUNT(?item) as ?count) WHERE {
  ?game wdt:P31/wdt:P279* wd:Q7889 .
  ?game wdt:P400 ?item .
  FILTER EXISTS { ?game p:%s [] } .
} GROUP BY ?item
HAVING (?count > %s)
ORDER BY DESC(?count) 
LIMIT 1000""" % (prop, self.property_threshold)

        result = collections.OrderedDict()
        sq = pywikibot.data.sparql.SparqlQuery()
        queryresult = sq.select(query)

        for resultitem in queryresult:
            qid = resultitem.get('item').replace(u'http://www.wikidata.org/entity/', u'')
            result[qid] = int(resultitem.get('count'))
        return result

    def get_game_totals(self, prop=None):
        """
        Get the game totals
        :param prop:  Wikidata Pid of the property. If set, just get the count of games with that property
        :return: number of games found
        """
        if prop:
            query = """SELECT (COUNT(?item) as ?count) WHERE {
  ?item wdt:P31/wdt:P279* wd:Q7889 .
  FILTER EXISTS { ?item p:%s [] } .
}""" % (prop,)
        else:
            query = """SELECT (COUNT(?item) as ?count) WHERE {
  ?item wdt:P31/wdt:P279* wd:Q7889 .
}"""
        sq = pywikibot.data.sparql.SparqlQuery()
        queryresult = sq.select(query)
        for resultitem in queryresult:
            # Just one result, return that right away
            return int(resultitem.get('count'))

    def run(self):
        """
        Starts the robot and do all the work.
        """
        logging.info("Retrieving collection information...")
        collections_counts = self.get_collection_information()
        logging.info("Collection retrieved: %s", len(collections_counts))
        for prop in self.properties:
            self.propertyData[prop] = self.get_property_info(prop)

        text = u'{{/Header}}\n{| class="wikitable sortable"\n'
        text += u'! colspan="2" |Top platforms (Minimum %s items)\n' % (self.collection_threshold, )
        text += u'! colspan="%s"|Top Properties (used at least %s times per collection)\n' % (len(self.properties), self.property_threshold, )
        text += u'|-\n'
        text += u'! Name\n'
        text += u'! Count\n'
        for prop in self.properties:
            text += u'! data-sort-type="number"|%s\n' % self.properties.get(prop)

        for collection in collections_counts:
            workcount = collections_counts.get(collection)
            item = pywikibot.ItemPage(self.repo, collection)
            item.get()

            text += u'|-\n'
            text += u'| {{Q|%s}}\n' % (collection,)
            text += u'| [[Wikidata:WikiProject Video games/Reports/Platform/%s|%s]] \n' % (item.labels['en'], workcount, )
            for prop in self.properties:
                propcount = self.propertyData.get(prop).get(collection)
                if not propcount:
                    propcount = 0
                percentage = round(1.0 * propcount / max(workcount, 1) * 100, 2)
                text += u'| {{/Cell|%s|%s}}\n' % (percentage, propcount)

        # Get the totals
        totalworks = self.get_game_totals()

        text += u'|- class="sortbottom"\n|\'\'\'Totals\'\'\' <small>(all games)<small>:\n| %s\n' % (totalworks,)
        for prop in self.properties:
            totalprop = self.get_game_totals(prop=prop)
            try:
                percentage = round(1.0 * totalprop / totalworks * 100, 2)
            except ZeroDivisionError:
                percentage = 0
            text += u'| {{/Cell|%s|%s}}\n' % (percentage, totalprop)
        text += u'|}\n'
        text += u'[[Category:WikiProject Video games|Property statistics]]\n'

        page = pywikibot.Page(self.repo, title=self.targetPageTitle)
        summary = u'Video games property usage stats'
        page.put(text, summary)


def main(*args):
    """
    Main function. Bot does all the work.
    """
    stats = VideoGamePropertyStatistics()
    stats.run()

if __name__ == "__main__":
    main()
VERBOSE:pywiki:Found 1 wikidata:wikidata processes running, including this one.
VERBOSE:pywiki:Found 1 commons:commons processes running, including this one.
Page [[wikidata:Wikidata:WikiProject Video games/Statistics/Platform]] saved
INFO:pywiki:Page [[wikidata:Wikidata:WikiProject Video games/Statistics/Platform]] saved