#!/usr/bin/python3
# -*- coding: utf-8 -*
# Copyright (C) 2017 Tetras Libre <contact@Tetras-Libre.fr>
# Author: Beniamine, David <David.Beniamine@Tetras-Libre.fr>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
from dateutil.parser import parse
from itertools import combinations
from zxcvbn import zxcvbn
from zxcvbn.matching import add_frequency_lists
from translations import tr

def add_dictionnaries():
    dicts = {}
    directory = os.path.dirname(os.path.realpath(__file__))+'/../data'
    for fn in os.listdir(directory):
        fn = directory+"/"+fn
        if os.path.isfile(fn):
            name = os.path.basename(os.path.splitext(fn)[0])
            with open(fn) as f:
                dicts[name] = f.read().splitlines()
    add_frequency_lists(dicts)


# Process user inputs:
#   Generate all possibile combinations of 2 parts of dates
def process_input(inputs):
    try :
        dates = []
        words = []
        for i in inputs:
            try:
                date = parse(i)
                dates += date.strftime("%d-%m-%y-%B-%Y-%A").split('-')
            except:
                words.append(i)
        for n in range(2, 4):
            for subset in combinations(dates, n):
                words.append("".join(subset))
        return words
    except:
        return None


def test_pass(password, inputs):

    # Read input
    add_dictionnaries()
    results = zxcvbn(password, process_input(inputs))
    lines = []

    lines.append("Résultats du test\n")
    lines.append("Nombre de tentatives : {}".format(results["guesses"]))

    lines.append("Temps requis pour craquer votre mot de passe")
    for key, value in results["crack_times_display"].items():
        lines.append("\t "+tr(key).capitalize()+" :\t **"+tr(value)+"**")

    lines.append("\n")
    lines.append("Methode de hack utilisées")
    # Print hack methods
    for seq in results["sequence"]:
        if seq["pattern"] == "bruteforce":
            lines.append("\tMot de passe trouvé par force brute")
        elif seq["pattern"] == "repeat":
            for match in seq["base_matches"]:
                line = "\tMot de passe trouvé par répétitions depuis"
                try:
                    line += "le dictionnaire '{}'".format(tr(match["dictionary_name"]))
                except:
                    line += "le motif '{}'".format(tr(match["token"]))
                finally:
                    lines.append(line)
        elif seq["pattern"] == "date":
            lines.append("\tMot de passe trouvé par essai de dates")
        elif seq["pattern"] == "sequence":
            lines.append("\tMot proche trouvé dans la séquence : '{}'".format(tr(seq["sequence_name"])))
        else:
            lines.append("\tMot proche trouvé dans le dictionnaire : '{}'".format(tr(seq["dictionary_name"])))

    lines.append("\n")

    for key, values in results["feedback"].items():
        if values != [] and values != "":
            lines.append("{} :".format(tr(key).capitalize()))
        else:
            continue
        if not isinstance(values, list):
            # Simplify things by always using lists
            values = [values]
        for val in values:
            lines.append("\t{}".format(tr(val)))

    valeur = ["Très faible", "Faible", "Tolérable", "Correct", "Bon"]
    lines.append("Score Global {}/4 : {}".format(results["score"], valeur[results["score"]]))

    return lines