#!/usr/bin/env python3

from Cryptotools.Groups.cyclic import Cyclic
from Cryptotools.Utils.utils import gcd
from Cryptotools.Numbers.primeNumber import isPrimeNumber
from random import choice


def operation(a, b, n):
    return (a ** b) % n

def test1(n):
    """
        We test with n is not prime but the order of the group is a prime number
    """
    g = list()
    g2 = list()
    for i in range(1, n):
        #if gcd(i, n) == 1:
        g.append(i)
    
    print(f"n = {n}")
    print(f"G = {g}")
    Gsorted = sorted(g)

    cyclic = Cyclic(g, n, operation)
    order = len(g) # https://en.wikipedia.org/wiki/Order_(group_theory)
    print(f"len: {order}")
    print(f"prime: {isPrimeNumber(order)}")
    g2 = list()
    for i in range(1, order):
        if gcd(i, order) == 1:
            g2.append(i)
            pass
    
    print(g2)
    # Pick a number in the previous list and check if we can generate all number with it
    item = choice(g2)
    print()
 
    # if the order is prime, the group is cyclic ?

    # Check if we have all items
    g3 = list()
    for i in range(1, n):
        res = operation(i, item, n)
        if gcd(res, item) == 1:
            g3.append(res)
            #print(res)
            pass

    G2sorted = sorted(g2)
    G3sorted = sorted(g3)
    print()
    # print(f"{g} = {cyclic.generator(g)}")
    gen = cyclic.generator()
    
    print(f"All generators: {cyclic.getGenerators()}")
    print(f"Is cyclic: {cyclic.isCyclic()}")

    print()
    print(G2sorted)
    print(G3sorted)
    if G3sorted == Gsorted:
        print(f"Matching with item {item}") # Always match with item 1

    # Check if the abelian group is respected
    print(f"It is an abelian group: {cyclic.closure()}\n")



test1(19)
test1(12)
