# EG10-10 Time Tracker with properties and exception handlers

import pickle
from BTCInput import *

# Utworzenie klasy Contact 

class Contact:
    
    __min_session_length = 0.5
    __max_session_length = 3.5

    
    @staticmethod
    def validate_session_length(session_length):
        '''
        Sprawdza poprawność czasu trwania sesji. Zwraca
        True jeśli czas trwania sesji jest prawidłowy lub False w przeciwnym przypadku
        '''
        if session_length < Session.__min_session_length:
            return False
        if session_length > Contact.max_session_length:
            return False
        return True

    __min_text_length = 4

    @staticmethod
    def valid_text(text):
        '''
        Sprawdza poprawność tekstu, który ma być przechowywany w obiekcie reprezentującym kontakt
        .
        Zwraca True, jeśli tekst jest prawidłowu i False, jeśli nie jest
        '''
        if len(text) < Contact.__min_text_length:
            return False
        else:
            return True

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        if not Contact.validate_text(name):
            raise Exception('Nieprawidłowe nazwisko')
        self.__name = name

    @property
    def address(self):
        return self.__address

    @address.setter
    def address(self,address):
        if not Contact.validate_text(address):
            raise Exception('Nieprawidłowy adres')
        self.__address = address

    @property
    def price(self):
        return self.__telephone

    @telephone.setter
    def telephone(self,telephone):
        if not Contact.validate_text(name):
            raise Exception('Nieprawidłowy adres')
        self.telephone = telephone


    def __init__(self, name, address, telephone):
        self.name = name
        self.address = address
        self.telephone = telephone
        self.__hours_worked = 0

    def get_hours_worked(self): 
        '''
        Pobiera liczbę godzin przepracowanych dla tego kontaktu
        '''
        return self.hours_worked 

    def add_session(self, session_length):
        '''
        Dodaje wartość parametru 
        do godzin przepracowanych na rzecz osoby reprezentowanej przez ten kontakt
        Zgłasza wyjątek, gdy podany czas trwania sesji jest nieprawidłowy.
        '''
        if not Contact.validate_session_length(session_length): 
           raise Exception('Nieprawidłowy czas trwania sesji')
        self.__hours_worked = self.__hours_worked + session_length
        return

def new_contact():
    '''
    Czyta nowy kontakt i go zapisuje
    '''
    print('Stwórz nowy kontakt')
    # dodanie atrybutów danych
    name=read_text('Wprowadź nazwisko: ')
    address=read_text('Wprowadź adres: ')
    telephone=read_text('Wprowadź telefon kontaktowy: ')
    # stworzenie nowego egzemplarza klasy
    try:
        new_contact=Contact(name=name,address=address,telephone=telephone)
    except Exception as e:
        print('Dodanie sesji nie powiodło się:', e)
        return
    # dodanie nowego kontaktu do listy kontaktów
    contacts.append(new_contact)

def find_contact(search_name):
    '''
    Znajduje kontakt o pasującym nazwisku 
    Zwraca egzemplarz kontaktu lub None, jeśli nie istnieje 
    kontakt o podanym nazwisku
    '''
    # usuń wszelkie białe spacje wokół nazwy do wyszukiwania
    search_name = search_name.strip()
    # konwertuj wyszukiwane nazwisko na małe litery
    search_name = search_name.lower()
    for contact in contacts:
        # pobierz nazwisko z kontaktu 
        name=contact.name
        # usuń wszelkie białe spacje wokół nazwy do wyszukiwania
        name=name.strip()
        # konwertuj wyszukiwane nazwisko na małe litery
        name = name.lower()
        # sprawdź, czy nazwiska do siebie pasują
        if name.startswith(search_name):
            # zwrócenie znalezionego kontaktu
            return contact
    # jeśli dotarliśmy do tego miejsca, to nie znaleziono kontaktu
    # o podanym nazwisku
    return None
    
def display_contact():
    '''
    Wczytuje nazwisko do wyszukania, a następnie wyświetla
    informacje dotyczące tego nazwiska lub
    komunikat informujący o tym, że nazwiska nie znaleziono
    '''
    print('Znajdź kontakt')
    search_name = read_text('Wprowadź nazwisko: ')
    contact=find_contact(search_name)
    if contact!=None:
        # Znaleziono szukany kontakt
        print('Nazwisko:', contact.name)
        print('Adres:', contact.address)
        print('Telefon:', contact.telephone)
        print('	Liczba godzin poświęconych sprawie:', contact.hours_worked)
    else:              
        print('Wprowadzone nazwisko nie zostało znalezione.')

def edit_contact():
    '''
    Czyta nazwisko do wyszukiwania, a następnie pozwala
    użytkownikowi edytować szczegóły wyszukanego kontaktu.
    Jeśli kontakt nie zostanie znaleziony, funkcja wyświetla
    komunikat informujący o tym, że nazwiska nie znaleziono
    '''
    print('Edytuj kontakt')
    search_name=read_text('Wprowadź nazwisko:')
    contact=find_contact(search_name)
    if contact!=None:
        # Znaleziono szukany kontakt
        try:
            print('Nazwisko: ',contact.name)
            new_name=read_text('Wprowadź nowe nazwisko lub . aby pozostawić je bez zmian: ')
            if new_name!='.':
                contact.name=new_name
            new_address=read_text('Wprowadź nowy adres lub ., aby pozostawić go bez zmian: ')
            if new_address!='.':
                contact.address=new_address
            new_phone=read_text('Wprowadź nowy numer telefonu lub ., aby pozostawić go bez zmian: ')
            if new_phone!='.':
                contact.telephone=new_phone
        except Exception as e:
            print('Dodanie sesji nie powiodło się:', e)
    else:              
        print('Wprowadzone nazwisko nie zostało znalezione.')

def add_session_to_contact():
    '''
    Czyta nazwisko do wyszukiwania, a następnie pozwala
    użytkownikowi wprowadzić sesję czasu pracy dla   
    tego klienta
    '''
    print('dodaj sesję')
    search_name=read_text('Wprowadź nazwisko:')
    contact=find_contact(search_name)
    if contact!=None:
        # Znaleziono szukany kontakt
        print('Nazwisko: ',contact.name)
        print('Godziny przepracowane wcześniej :', contact.hours_worked)
        session_length=read_float(prompt='Czas trwania sesji: ')
        try:
            contact.add_session(hours_worked)
            print('Godziny przepracowane po aktualizacji:', contact.hours_worked)
        except Exception as e:
            print('Dodanie sesji nie powiodło się:', e)
    else:              
        print('Wprowadzone nazwisko nie zostało znalezione.')
    
def save_contacts(file_name):
    '''
    Zapisuje kontakty w pliku o podanej nazwie
    Kontakty są przechowywane w postaci binarnej, w pliku .pickle
    Jeśli zapis nie powiedzie się, program zgłosi wyjątki 
    '''
    print('zapisywanie kontaktów')
    with open(file_name,'wb') as out_file:
        pickle.dump(contacts,out_file)

def load_contacts(file_name):
    '''
    Ładuje kontakty z pliku o podanej nazwie
    Kontakty są przechowywane w postaci binarnej, w pliku .pickle
    Jeśli ładowanie pliku się nie powiedzie, funkcja będzie zgłaszała wyjątki
    '''
    global contacts
    print('Ładowanie kontaktów')
    with open(file_name,'rb') as input_file:
        contacts=pickle.load(input_file)

menu='''Time Tracker

1. Nowy kontakt
2. Znajdź kontakt
3. Edytuj kontakt
4. Dodaj sesję
5. Wyjście z programu

Wprowadź polecenie: '''

filename='pcontacts.pickle'
try:
    load_contacts(filename)
except:
    print('Nie znaleziono pliku kontaktów')
    contacts=[]

while True:
    command=read_int_ranged(prompt=menu,min_value=1,max_value=3)
    if command==1:
        new_contact()
    elif command==2:
        display_contact()
    elif command==3:
        edit_contact()
    elif command==4:
        add_session_to_contact()
    elif command==5:
        save_contacts(file_name)
        break



