import math

PER_SIVU = 5

def valitse_artisti(levy):
    return levy["artisti"]

def valitse_albumi(levy):
    return levy["albumi"]
    
def valitse_kpl_n(levy):
    return levy["kpl_n"]
    
def valitse_kesto(levy):
    return levy["kesto"]

def valitse_julkaisuvuosi(levy):
    return levy["julkaisuvuosi"]

def kysy_luku(kysymys):
    """
    Kysyy käyttäjältä kokonaisluvun käyttäen pyynnössä ohjeena
    kysymys-merkkijonoa. Lukua pyydetään, kunnes saadaan syöte,
    joka on mahdollista muuttaa kokonaisluvuksi.

    Palauttaa annetun luvun kokonaislukuna.
    """

    while True:
        try:
            luku = int(input(kysymys))
        except ValueError:
            print("Arvon tulee olla kokonaisluku")
        else:
            return luku    
            
def kysy_aika(kysymys):
    """
    Kysyy käyttäjältä ajan käyttäen pyynnössä ohjeena kysymys-
    merkkijonoa. Pyyntö toistetaan kunnes käyttäjä antaa ajan
    muodossa tunnit:minuutit:sekunnit tai minuutit:sekunnit.
    Kustakin osasta tarkistetaan, että ne ovat sekä lukuja, että
    sallituissa rajoissa (0-59).

    Funktio palauttaa aina ajan, jossa on kaikki kolme osaa.
    Tunnit asetetaan nollaksi, jos käyttäjä ei syöttänyt tuntiosaa.
    """

    while True:
        osat = input(kysymys).split(":")
        if len(osat) == 3:
            h, min, s = osat
        elif len(osat) == 2:
            min, s = osat
            h = "0"
        else:
            print("Anna aika muodossa tunnit:minuutit:sekunnit tai minuutit:sekunnit")
            continue
            
        try:
            h = int(h)
            min = int(min)
            s = int(s)
        except ValueError:
            print("Aikojen on oltava kokonaislukuja")
            continue
            
        if not (0 <= min <= 59):
            print("Minuuttien on oltava välillä 0-59")
            continue
        if not(0 <= s <= 59):
            print("Sekuntien on oltava välillä 0-59")
            continue
        if h < 0:
            print("Tuntien on oltava positiivinen kokonaisluku")
            continue
            
        return "{}:{:02}:{:02}".format(h, min, s)

def lataa_kokoelma():
    """
    Luo testikokoelman. Palauttaa listan, joka sisältää viiden avain-arvo-parin
    sanakirjoja.
    Sanakirjan avaimet vastaavat seuraavia tietoja:
    "artisti" - artisti nimi
    "albumi" - levyn nimi 
    "kpl_n" - kappaleiden määrä
    "kesto" - kesto
    "julkaisuvuosi" - julkaisuvuosi
    """
    
    kokoelma = [
        {
            "artisti": "Alcest",
            "albumi": "Kodama",
            "kpl_n": 6,
            "kesto": "0:42:15",
            "julkaisuvuosi": 2016
        },
        {
            "artisti": "Canaan",
            "albumi": "A Calling to Weakness",
            "kpl_n": 17,
            "kesto": "1:11:17",
            "julkaisuvuosi": 2002
        },
        {
            "artisti": "Deftones",
            "albumi": "Gore",
            "kpl_n": 11,
            "kesto": "0:48:13",
            "julkaisuvuosi": 2016
        },
        {
            "artisti": "Funeralium",
            "albumi": "Deceived Idealism",
            "kpl_n": 6,
            "kesto": "1:28:22",
            "julkaisuvuosi": 2013
        },
        {
            "artisti": "IU",
            "albumi": "Modern Times",
            "kpl_n": 13,
            "kesto": "47:14",
            "julkaisuvuosi": 2013
        },
        {
            "artisti": "Mono",
            "albumi": "You Are There",
            "kpl_n": 6,
            "kesto": "1:00:01",
            "julkaisuvuosi": 2006
        },
        {
            "artisti": "Panopticon",
            "albumi": "Roads to the North",
            "kpl_n": 8,
            "kesto": "1:11:07",
            "julkaisuvuosi": 2014
        },
        {
            "artisti": "PassCode",
            "albumi": "Clarity",
            "kpl_n": 13,
            "kesto": "0:49:27",
            "julkaisuvuosi": 2019
        },
        {
            "artisti": "Scandal",
            "albumi": "Hello World",
            "kpl_n": 13,
            "kesto": "53:22",
            "julkaisuvuosi": 2014
        },
        {
            "artisti": "Slipknot",
            "albumi": "Iowa",
            "kpl_n": 14,
            "kesto": "1:06:24",
            "julkaisuvuosi": 2001
        },
        {
            "artisti": "Wolves in the Throne Room",
            "albumi": "Thrice Woven",
            "kpl_n": 5,
            "kesto": "42:19",
            "julkaisuvuosi": 2017
        },
    ]
    return kokoelma

def tallenna_kokoelma(kokoelma):
    """
    Tallentaa kokoelman, joskus tulevaisuudessa. 
    """
    
    pass
    
def lisaa(kokoelma):
    """
    Lisää albumeita parametrina saatuun kokoelmaan. Kunkin albumin kohdalla
    pyydetään syöttämään albumin nimi, artisti, kappaleiden lukumäärä, kesto ja
    julkaisuvuosi. Syötetyt albumit lisätään sanakirjoina kokoelma-listaan. Funktio
    jatkaa uusien lisäyksien kysymistä kunnes levyn nimi jätetään tyhjäksi.
    """

    print("Täytä lisättävän levyn tiedot. Jätä levyn nimi tyhjäksi lopettaaksesi")
    while True:
        levy = input("Levyn nimi: ")
        if not levy:
            break
            
        artisti = input("Artistin nimi: ")
        kpl_n = kysy_luku("Kappaleiden lukumäärä: ")
        kesto = kysy_aika("Kesto: ")
        vuosi = kysy_luku("Julkaisuvuosi: ")
        kokoelma.append({
            "artisti": artisti,
            "albumi": levy,
            "kpl_n": kpl_n,
            "kesto": kesto,
            "julkaisuvuosi": vuosi
        })
 
def poista(kokoelma):
    """
    Poistaa albumeita kokoelma-listasta. Poistettava albumi valitaan syöttämällä
    sen nimi sekä artistin nimi.
    """

    print("Täytä poistettavan levyn nimi ja artistin nimi. Jätä levyn nimi tyhjäksi lopettaaksesi")
    while True:
        nimi = input("Anna poistettavan levyn nimi: ").lower()
        if not nimi:
            break
        artisti = input("Anna poistettavan levyn artisti: ").lower()
        for levy in kokoelma[:]:
            if levy["artisti"].lower() == artisti and levy["albumi"].lower() == nimi:
                kokoelma.remove(levy)
                print("Levy poistettu")

def muuta_kenttia(levy):
    """
    Muuttaa parametrina annetun levy-sanakirjan avainten arvoja. Käyttäjä valitsee
    muutettavan kentän numerolla ja syöttää sitten uuden arvon. Jos käyttäjä jättää
    kentän tyhjäksi, funktion suoritus päättyy. Jokainen muutos tallennetaan
    sanakirjaan heti kun se on syötetty.
    """

    print("Nykyiset tiedot:")
    print("{artisti}, {albumi}, {kpl_n}, {kesto}, {julkaisuvuosi}".format(**levy))
    print("Valitse muutettava kenttä syöttämällä sen numero. Jätä tyhjäksi lopettaaksesi.")
    print("1 - artisti")
    print("2 - levyn nimi")
    print("3 - kappaleiden määrä")
    print("4 - levyn kesto")
    print("5 - julkaisuvuosi")
    while True:
        kentta = input("Valitse kenttä (1-5): ")
        if not kentta:
            break
        elif kentta == "1":
            levy["artisti"] = input("Anna artistin nimi: ")
        elif kentta == "2":
            levy["albumi"] = input("Anna levyn nimi: ")
        elif kentta == "3":
            levy["kpl_n"] = kysy_luku("Anna kappaleiden määrä: ")
        elif kentta == "4":
            levy["kesto"] = kysy_aika("Anna levyn kesto: ")
        elif kentta == "5":
            levy["julkaisuvuosi"] = kysy_luku("Anna julkaisuvuosi: ")
        else:
            print("Kenttää ei ole olemassa")

def muokkaa(kokoelma):
    """
    Muokkaa kokoelma-listassa olevien albumien tietoja. Tässä funktiossa käyttäjä valitsee
    muokattavan albumin syöttämällä sen nimen sekä artistin nimen. Varsinainen muokkaus
    tehdään muuta_kenttia-funktiossa.
    """

    print("Täytä muutettavan levyn nimi ja artistin nimi. Jätä levyn nimi tyhjäksi lopettaaksesi")
    while True:
        nimi = input("Anna muutettavan levyn nimi: ").lower()
        if not nimi:
            break
        artisti = input("Anna muutettavan levyn artisti: ").lower()
        for levy in kokoelma[:]:
            if levy["artisti"].lower() == artisti and levy["albumi"].lower() == nimi:
                muuta_kenttia(levy)
                print("Levyn tiedot muutettu")

def jarjesta(kokoelma):
    """
    Järjestää parametrissa olevan kokoelma-listan. Pyytää käyttäjää valitsemaan
    kentän, jonka perusteella järjestäminen tehdään, sekä sen onko järjestys
    nouseva vai laskeva. Kokoelma järjestään "paikallaan", eli siitä ei luoda uutta
    kopiota.
    """

    print("Valitse kenttä jonka mukaan kokoelma järjestetään syöttämällä kenttää vastaava numero")
    print("1 - artisti")
    print("2 - levyn nimi")
    print("3 - kappaleiden määrä")
    print("4 - levyn kesto")
    print("5 - julkaisuvuosi")
    kentta = input("Valitse kenttä (1-5): ")
    jarjestys = input("Järjestys; (l)askeva vai (n)ouseva: ").lower()
    if jarjestys == "l":    
        kaanna = True
    else:
        kaanna = False
    if kentta == "1":
        kokoelma.sort(key=valitse_artisti, reverse=kaanna)
    elif kentta == "2":
        kokoelma.sort(key=valitse_albumi, reverse=kaanna)
    elif kentta == "3":
        kokoelma.sort(key=valitse_kpl_n, reverse=kaanna)
    elif kentta == "4":
        kokoelma.sort(key=valitse_kesto, reverse=kaanna)
    elif kentta == "5":
        kokoelma.sort(key=valitse_julkaisuvuosi, reverse=kaanna)
    else: 
        print("Kenttää ei ole olemassa")
  
def muotoile_sivu(rivit, sivu):
    """
    Tulostaa yhden "sivun". Varsinainen näytettävä sisältö on rivit-parametrissa.
    Parametrissa sivu olevaa sivun numeroa käytetään numeroinnissa: kunkin albumin eteen
    tulostetaan sen järjestysnumero kokoelmassa.
    """

    for i, levy in enumerate(rivit, sivu * PER_SIVU + 1):
        print("{i:2}. {artisti} - {albumi} ({vuosi}) [{kpl_n}] [{kesto}]".format(
            i=i,
            artisti=levy["artisti"],
            albumi=levy["albumi"],
            kpl_n=levy["kpl_n"],
            kesto=levy["kesto"].lstrip("0:"),
            vuosi=levy["julkaisuvuosi"]
        ))

def tulosta(kokoelma):
    """
    Tulostaa kokoelma-parametrissa olevan kokoelman sivutettuna. Kullekin "sivulle"
    tulee PER_SIVU-vakiossa osoitettu määrä tulostettavia rivejä. Jokaisen "sivun"
    tulostuksen jälkeen odotetaan, että käyttäjä antaa syötteen jatkamista varten.
    """

    tulostuksia = math.ceil(len(kokoelma) / PER_SIVU)
    for i in range(tulostuksia):
        alku = i * PER_SIVU
        loppu = (i + 1) * PER_SIVU
        muotoile_sivu(kokoelma[alku:loppu], i)
        if i < tulostuksia - 1:
            input("   -- paina enter jatkaaksesi tulostusta --")        

albumit = lataa_kokoelma()
print("Tämä ohjelma ylläpitää levykokoelmaa. Voit valita seuraavista toiminnoista:")
print("(L)isää uusia levyjä")
print("(M)uokkaa levyjä")
print("(P)oista levyjä")
print("(J)ärjestä kokoelma")
print("(T)ulosta kokoelma")
print("(Q)uittaa")
while True:
    valinta = input("Tee valintasi: ").strip().lower()
    if valinta == "l":
        lisaa(albumit)
    elif valinta == "p":
        poista(albumit)
    elif valinta == "j":
        jarjesta(albumit)
    elif valinta == "t":
        tulosta(albumit)
    elif valinta == "q":
        break    
    else:
        print("Valitsemaasi toimintoa ei ole olemassa")
tallenna_kokoelma(albumit)
