import numpy as np
from gmpy2 import mpz

class BinSequence:
    def __init__(self, value=0, length=0):
        self.x = mpz(value)
        self.len = length
    
    def copy(self):
        return BinSequence(self.x, self.len)
    
    def append_0(self):
        self.len += 1
        return self
    
    def append_1(self):
        self.x = self.x.bit_set(self.len)
        self.len += 1
        return self
    
    def all_bits_set(self):
        if self.len == 0:
            return False
        tmp = mpz(0)
        tmp = tmp.bit_set(self.len)
        return tmp == self.x + 1
    
    def to_array(self):
        array = np.zeros((self.len,))
        next_1 = self.x.bit_scan1(0)
        while next_1 != None:
            array[next_1] = 1
            next_1 = self.x.bit_scan1(next_1 + 1)
        return array
    
    def to_mpz(self):
        return self.x
                
class BinSequenceTests:
    def correctness_test(self):
        s = BinSequence()
        
        s.append_0()
        a = s.to_array()
        assert a[0] == 0
        assert len(a) == 1
        assert s.len == 1
        
        s.append_1()
        print(s.x)
        a = s.to_array()
        assert a[0] == 0
        assert a[1] == 1
        assert len(a) == 2
        assert s.len == 2
        
        s1 = s.copy()
        assert s1.x == s.x
        assert s1.len == s.len
        
        s = BinSequence(1, 2)
        a = s.to_array()
        assert a[0] == 1
        assert a[1] == 0
        
    def all_bits_set_test(self):
        s = BinSequence()
        assert s.all_bits_set() == False
        s.append_1()
        assert s.all_bits_set() == True
        s.append_1()
        assert s.all_bits_set() == True
        s.append_0()
        assert s.all_bits_set() == False
        print("Success")
        
# tests = BinSequenceTests()
# tests.correctness_test()
# tests.all_bits_set_test()