﻿from music.note import Note
from music import scales, triad, settings, guitar

AllNotes = settings.get_all_notes()
DistancesBetweenNotes = settings.get_distance_between_notes()


def print_notes(notes):

    str_notes = ''

    for current_note in notes:

        if len(str_notes) > 0:
            str_notes += ' - '
        str_notes += current_note.Name

    print str_notes

all_scales = {
    '1. Natural scale': '1 2 3 4 5 6 7',
    '2. Major': '1 3 5',
    '3. Major 7': '1 3 5 7',
    '4. Minor': '1 3b 5',
    '5. Pentatonic major': '1 2 3 5 6'}

print 'What do you want to do?'
print '[1] Build scales'
print '[2] Print scales in a guitar'
print '[3] Build triads'
print '[4] Build chords'
option = int(raw_input('Your option: '))

if option == 1:
    # Print notes that compose scales
    for note in AllNotes:

        print '\n\nSCALES FOR ' + note.Name + ':\n',

        for scale_name in all_scales.keys():

            print scale_name + ' in ' + note.Name + ': ',

            notes_in_scale = scales.get_scale_from_positions(note, all_scales[scale_name])

            print_notes(notes_in_scale)

elif option == 2:
    # Print all scales marking the notes in a guitar
    for note in AllNotes:

        print '\n\nSCALES FOR ' + note.Name + ':\n',

        wanted_scales = {
            'Major scale': '1 2 3 4 5 6 7',
            'Minor scale': '1 2 3b 4 5 6b 7b',
            'Minor pentatonic': '1 3b 4 5 7b',
            'Major pentatonic': '1 3 5 6',
            'Rock pentatonic': '1 3b 4 5# 7b'
            }

        for scale_name in wanted_scales.keys():

            print scale_name + ' in ' + note.Name + ':\n',

            # Get a guitar: strings and notes in each one
            guitar_strings = guitar.get_guitar()

            # Get the scale we want to print
            notes_in_scale = scales.get_scale_from_positions(note, wanted_scales[scale_name])

            # Loop through all the strings in a guitar (6 in classical guitar)
            for string in guitar_strings:

                # Loop through all the notes in a string
                for string_note in string['StringNotes']:

                    # Build an array with the names of the notes in scale
                    scale_note_names = map(lambda x: x.Name, notes_in_scale)

                    if string_note.Name in scale_note_names:
                        # If note is in the list of notes that have to be marked, mark it

                        # If its name has two characters (because it is sharped or bemol), don't print a space. Else,
                        # print it, to keep alignment
                        if len(string_note.Name) == 2:
                            print '[' + string_note.Name + ']',
                        else:
                            print '[' + string_note.Name + ' ]',
                    else:
                        # Else, just print the string
                        print ' -  ',
                print ''
elif option == 3:
    # Print notes that compose scales
    for note in AllNotes:

        triads = triad.get_all_from_scale(note)

        for current_triad in triads:

            print 'Triad for', current_triad['ReferenceNote'].Name, ':',
            print current_triad['Notes'][0].Name,
            print current_triad['Notes'][1].Name,
            print current_triad['Notes'][2].Name,

            print '=>', current_triad['ReferenceNote'].Name + current_triad['ResultingVariation']
elif option == 4:

    # Get all triads, then sort resulting array by resulting note
    print 'Chords:'

    all_triads = []

    # Get all triads for all scales
    for note in AllNotes:
        all_triads.extend(triad.get_all_from_scale(note))

    # Remove duplicates
    unique_triads = []

    for current_triad in all_triads:

        # Get full name for chord (including minor, major,...)
        current_triad_full_name = current_triad['ReferenceNote'].Name + current_triad['ResultingVariation']

        triad_already_exists = False

        for unique_triad in unique_triads:

            # Get full name for chord (including minor, major,...)
            current_unique_triad_full_name = unique_triad['ReferenceNote'].Name + unique_triad['ResultingVariation']

            # Verify it has not already been added
            if current_unique_triad_full_name == current_triad_full_name:
                triad_already_exists = True
                break

        if not triad_already_exists:
            unique_triads.append(current_triad)

    # Sort all triads in list by their resulting chord
    all_triads_sorted = sorted(unique_triads, key=lambda item: item['ReferenceNote'].Name)

    for current_triad in all_triads_sorted:

        print current_triad['ReferenceNote'].Name + current_triad['ResultingVariation'], '=>',
        print current_triad['Notes'][0].Name,
        print current_triad['Notes'][1].Name,
        print current_triad['Notes'][2].Name