# coding: utf8
# Debian Contributors data source data mining tools
#
# Copyright (C) 2013--2014  Enrico Zini <enrico@debian.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from .. import scanner
from ..parser import Fail
from ..types import *
import datetime
import random

__all__ = ["Mock"]


class Generator(object):
    def __init__(self):
        self.allowed_chars = "abcdefghijklmnopqrstuvwxyz"
        self.fpr_allowed_chars = "ABCDEF0123456789"
        self.today = datetime.date.today()

    def make_string(self, string_len):
        return "".join(random.choice(self.allowed_chars) for i in range(string_len))

    def make_username(self):
        return self.make_string(random.randrange(3, 15))

    def make_fingerprint(self):
        return "".join(random.choice(self.fpr_allowed_chars) for i in range(40))

    def make_email_domain(self):
        components = []
        for i in range(random.randrange(1, 4)):
            components.append(self.make_string(random.randrange(3, 10)))
        components.append(self.make_string(random.randrange(2, 4)))
        return ".".join(components)

    def make_contribution_range(self):
        date_until = self.today - datetime.timedelta(days=random.triangular(1, 365 * 5))
        date_since = date_until - datetime.timedelta(days=random.triangular(1, 365 * 10))
        return date_since, date_until

    def make_person(self):
        res = {
            "user": self.make_username(),
            "name": " ".join((self.make_string(random.randrange(3, 8)).capitalize(),
                              self.make_string(random.randrange(3, 8)).capitalize())),
            "fpr": self.make_fingerprint(),
        }
        res["email"] = "@".join((res["user"], self.make_email_domain()))
        return res

    def make_identifier(self, person, type):
        if type == "login":
            return Identifier(type, person["user"], person["name"])
        elif type == "email":
            return Identifier(type, person["email"], person["name"])
        elif type == "fpr":
            return Identifier(type, person["fpr"], person["name"])
        elif type == "url":
            return Identifier(type, "https://example.org/users/" + person["user"])
        else:
            raise KeyError("Identifier type {} is not supported".format(type))


class Mock(scanner.Scanner):
    """
    Generate random contributions for random people

    Example::

        identifier_type: email
        method: mock
        count: 10000
    """
    identifier_type = scanner.IdentifierTypeField(help_text="""
                            identifier type
                            """)
    count = scanner.IntegerField(default=1000, help_text="""
                                     Number of contributions to generate.
                                     """)
    url = scanner.CharField(help_text="""
                            template used to build URLs to link to people's
                            contributions. ``{email}`` will be replaced with
                            the email address, ``{user}`` will be replaced with
                            the user name, ``{fpr}`` will be replaced with
                            the user key fingerprint.
                            """)

    def scan(self):
        gen = Generator()
        for i in range(self.count):
            person = gen.make_person()
            date_since, date_until = gen.make_contribution_range()
            url = self.url.format(**person) if self.url else None
            ident = gen.make_identifier(person, self.identifier_type)
            yield ident, date_since, date_until, url
