import math

BIASED_COIN = 0
NAIVE = 1
MARGINAL_BALANCE = 0
RANGE = 1
SD = 2
VARIANCE = 3
NUMERIC = 0
ALPHA = 1
MIX = 2
SEQUENTIAL = 0
RANDOM = 1
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
NUMBER_LETTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

class Trial:
    def __init__(self, setting):
        self.id = setting.value('id')
        self.title = setting.value('title')
        self.code = setting.value('code')
        self.created = setting.value('created')
        self.modified = setting.value('modified')
        self.prob_method = setting.value('prob_method')
        self.base_prob = setting.value('base_prob')
        self.dist_method = setting.value('dist_method')
        self.identifier_type = setting.value('identifier_type')
        self.identifier_order = setting.value('identifier_order')
        self.identifier_length = setting.value('identifier_length')
        self.recycle_ids = setting.value('recycle_ids')
        self.new_subject_random = setting.value('new_subject_random')
        self.arms_weight = setting.value('arms_weight')

    def get_max_sample_size(self):
        base = 10
        if self.identifier_type == ALPHA:
            base = 26
        elif self.identifier_type == MIX:
            base = 36
        ss = math.pow(base, self.identifier_length)
        return ss, self.format_unit(ss)

    def format_unit(self, size):
        power = 1000
        n = 0
        power_labels = {0: '', 1: ' K', 2: ' M', 3: ' G', 4: ' T', 5: ' P'}
        while size > power:
            size //= power
            n += 1
        size = int(size)
        return '{}{}'.format(size, power_labels[n])

    def format_subject_identifier(self, value):
        length = int(self.identifier_length)
        if self.identifier_type == NUMERIC:
            return str(value).zfill(length)
        base = [10, 26, 36][self.identifier_type]
        z = ['0', 'A', '0'][self.identifier_type]
        lst = number_to_base(value, base)
        w = ['', LETTERS, NUMBER_LETTERS][self.identifier_type]
        lst = ''.join(list(map(lambda x: w[x], lst)))
        lst = lst.zfill(length)
        lst = lst.replace('0', z)
        return lst


def number_to_base(n, b):
    if n == 0:
        return [0]
    digits = []
    while n:
        digits.append(int(n % b))
        n //= b
    return digits[::-1]


