import urllib.request, random, ssl
import operator


def getLetterFreqs(text):
    frequency = {}
    for ascii in range(ord('a'), ord('a')+26):
        frequency[chr(ascii)] = float(text.count(chr(ascii)))/len(text)

    sum_freqs_squared = 0.0
    for ltr in frequency:
        sum_freqs_squared += frequency[ltr]*frequency[ltr]
    return sum_freqs_squared

def getTextOnly(text):
    # Usuwanie wszystkich niealfanumerycznych znaków
    # Można to zrobić na wiele sposobów, ale najprostszy jest ten:
    modifiedText = str(text.strip())
    modifiedText = modifiedText.replace(" ", "")
    modifiedText = " ".join(modifiedText.split())
    modifiedText = modifiedText.lower()
    return modifiedText

def getEncryptedData():
    encryptedFilePath = "https://raw.githubusercontent.com/noidentity29/AppliedCryptoPython/master/encryptedmoby.txt"
    
    response = urllib.request.urlopen(encryptedFilePath, context=ssl._create_unverified_context())
    readText = response.read()
    textOnly = getTextOnly(readText)
    return textOnly

def getFitnessScore(message, longerwords):

    score = 0.0
    for word in longerwords:
        wordWeight = message.count(word)
        if wordWeight>0:
            score += wordWeight * 50 * len(word)
    return score

def getDictionary():
    
    commonWordsPath = "https://raw.githubusercontent.com/noidentity29/AppliedCryptoPython/master/common_en_words.txt"
    ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    
    # Tworzenie zapytania URL
    response = urllib.request.urlopen(commonWordsPath, context=ssl._create_unverified_context())
    readText = response.read()

    # Plik jest w formacie binarnym
    # Dekodowanie
    fileOfWords = readText.decode('utf-8')

    # Tworzenie listy słów
    words = fileOfWords.split()

    # Usuwanie krótszych słów
    longerwords = list(filter(lambda x: len(x)> 2, words))

    return longerwords

def getKeyLength(encryptedText):
    highest = 0
    highCtr = 0
    encryptedText = encryptedText.lower()
    for KeyLength in range(1,26):
        sampling = encryptedText[::KeyLength]
        freqCheck =  getFreqs(sampling)
        if highest < freqCheck:
            highest = freqCheck
            highCtr = KeyLength

    return highCtr

def getFreqs(text):
    frequency = {}
    for ascii in range(ord('a'), ord('a')+26):
        frequency[chr(ascii)] = float(text.count(chr(ascii)))/len(text)

    sum_freqs_squared = 0.0
    for ltr in frequency:
        sum_freqs_squared += frequency[ltr]*frequency[ltr]
    return sum_freqs_squared

myDictionary = getDictionary()
cipherText = getEncryptedData()
freqScore = getLetterFreqs(cipherText)
fitScore = getFitnessScore(cipherText, myDictionary)
keyLength = getKeyLength(cipherText)

print()
print("Suma kwadratów częstości znaków dla tego pliku jest równa: ", freqScore)
print()
print("Wskaźnik dopasowania: ", fitScore)
print()
print("Długość użytego klucza to: ", keyLength)
print()
