import hashlib
import os

class BankAccount:

    def __init__(self, name, balance):
        self.name = name
        self.__balance = balance

    @property
    def my_balance(self):
        return self.__balance

    @my_balance.setter
    def my_balance(self, value):
        if not isinstance(value, (int, float)):
            raise ValueError('Баланс должен быть числом')

    @my_balance.deleter
    def my_balance(self):
        del self.__balance


class MagicBox:
    def __init__(self, contents=None):
        self._contents = contents

    @property
    def contents(self):
        if self._contents == "rabbit":
            return "A magical rabbit!"
        else:
            return self._contents
    
    @contents.setter
    def entity(self, new_contents):
        if new_contents == "wishes":
            print("Your wishes are granted!")
            self._contents = new_contents
        else:
            print("the magic didn't work this time.")
            self._contents = new_contents


class Celsius:

    def __init__(self, temp) -> None:
        self.__temperature = temp

    def to_fahrenheit(self):
        return self.__temperature*9/5 + 32

    @property
    def temperature(self):
        return self.__temperature

    @temperature.setter
    def temperature(self, value):
        if value < -273.15:
            raise ValueError("Температура должна быть больше 273.15")
        else:
            self.__temperature = value


class File:

    def __init__(self, size_in_bytes):
        self._size_in_bytes = size_in_bytes

    @property
    def size(self):
        if self._size_in_bytes < 1024:
            return f"{self._size_in_bytes} B"
        elif self._size_in_bytes < 1048576:
            return "%.2f KB" % (self._size_in_bytes/1024.0)
        elif self._size_in_bytes < 1073741824:
            return "%.2f MB" % (self._size_in_bytes/1048576.0)
        else:
            return "%.2f GB" % (self._size_in_bytes/1073741824.0)

    @size.setter
    def size(self, value):
        self._size_in_bytes = value


class Notebook:

    def __init__(self, notes: list):
        self._notes = notes

    @property
    def notes_list(self):
        for i, j in enumerate(self._notes):
            print(f"{i+1}.{j}")


class User:
    def __init__(self, name, password) -> None:
        self.name = name
        self.password = password

    @property
    def password(self):
        raise AttributeError("Пароль можно только менять, нельзя смотреть")

    @password.setter
    def password(self, plaintext):
        salt = os.urandom(32)
        self._hashed_password = hashlib.pbkdf2_hmac(
            "sha256", plaintext.encode("utf-8"), salt, 100_000
        )


class Money:
    def __init__(self, dollars, cents):
        # self.total_cents = 0
        self.total_cents = dollars*100 + cents

    @property
    def dollars(self):
        return self.total_cents//100

    @dollars.setter
    def dollars(self, value):
        if not isinstance(value, (int)):
            print("Error dollars")
            return
        if value < 0:
            print("Error dollars")
            return
        else:
            self.total_cents = self.total_cents%100 + value*100

    @property
    def cents(self):
        return self.total_cents%100

    @cents.setter
    def cents(self, value):
        if not isinstance(value, (int)): 
            print("Error cents")
        elif  value < 0 or value >= 100:
            print("Error cents")
        else:
            self.total_cents = (self.total_cents//100)*100 + value

    def __str__(self) -> str:
        return f"Ваше состояние составляет {self.total_cents//100} долларов {self.total_cents%100} центов"


"""Вычисляемые войства"""

class Square:
    def __init__(self, a) -> None:
        self.__side = a
        self.__area = None
        self.__perimeter = None

    @property
    def side(self):
        return self.__side

    @side.setter
    def side(self, value):
        self.__side = value
        self.__area = None
        self.__perimeter = None

    @property
    def area(self):
        if self.__area == None:
            print('calculate area')
            self.__area = self.__side**2
        return self.__area

    @property
    def perimeter(self):
        if self.__perimeter == None:
            print('calculate perimeter')
            self.__perimeter = self.__side*4
        return self.__perimeter


class Rectangle:
    def __init__(self, length, width):
        self.__length = length
        self.__width = width
        self.__area = None

    @property
    def area(self):
        if self.__area == None:
            self.__area = self.__length*self.__width
        return self.__area

    
class Date:

    def __init__(self, day, month, year) -> None:
        self.day = day
        self.month = month
        self.year = year

    @property
    def date(self):
        return "%02d/%02d/%04d" % (self.day, self.month, self.year)

    @property
    def usa_date(self):
        return "%02d-%02d-%04d" % (self.month, self.day, self.year)


class Password:

    def __init__(self, password) -> None:
        self.__password = password

    @property
    def password(self):
        return self.__password

    @password.setter
    def password(self, value):
        self.__password = value

    @property
    def strength(self):
        if len(self.password) < 8:
            return "Weak"
        elif len(self.password) >= 12:
            return "Strong"
        else:
            return "Medium"


def main():

    pass_1 = Password("Alligator34")
    assert pass_1.password == "Alligator34"
    assert pass_1.strength == "Medium"  
    assert len(pass_1.__dict__) == 1, 'У ЭК должен храниться только один атрибут'

    pass_2 = Password("Alligator345678")
    assert pass_2.password == "Alligator345678"
    assert pass_2.strength == "Strong"
    pass_1.password = "123"
    assert pass_1.strength == "Weak"
    assert len(pass_2.__dict__) == 1, 'У ЭК должен храниться только один атрибут'

    pass_3 = Password("345678")
    assert pass_3.strength == "Weak"
    print('Good')
    assert len(pass_3.__dict__) == 1, 'У ЭК должен храниться только один атрибут'

    # acc = BankAccount('Ivan', 200)
    # print(acc.my_balance)

    '''
    date = Date(3, 4, 2001)
    print(date.date)
    print(date.usa_date)
    '''

    # one_dollar = 1
    # print(f"{one_dollar:05}")

    '''
    note = Notebook(['Buy Potato', 'Buy Carrot', 'Wash car'])
    note.notes_list
    '''

    '''
    bill = Money(101, 99)
    assert isinstance(bill, Money)

    print(bill.__dict__.keys())

    print(bill)  # Ваше состояние составляет 101 долларов 99 центов
    print(bill.dollars, bill.cents)  # 101 99
    print(bill.total_cents)
    bill.dollars = 666
    print(bill.total_cents)
    print(bill)  # Ваше состояние составляет 666 долларов 99 центов
    bill.cents = 12
    print(bill.total_cents)
    print(bill)  # Ваше состояние составляет 666 долларов 12 центов

    print(bill.total_cents)

    assert bill.total_cents == 66612
    assert list(bill.__dict__.keys()) == ['total_cents']

    ken = Money(111, 90)
    assert isinstance(ken, Money)
    print(ken)
    ken.dollars = 'hello'  # Error dollars
    ken.dollars = 0
    print(ken)
    ken.cents = [1, 2, 3]  # Error cents
    ken.cents = 100  # Error cents
    ken.cents = 99
    print(ken)
    '''


    '''
    box = MagicBox("rubies")
    print(box.contents)
    print(box._contents)
    box.entity = "wishes"
    print(box._contents)
    print(box.entity)
    '''

    '''
    cel = Celsius(12.0)
    cel.temperature = 15
    cel.temperature = -300
    print(cel.temperature)
    '''



if __name__ == '__main__':
    main()