from music21 import converter, note, chord, stream, tempo
import random
import matplotlib.pyplot as plt

# Предварительно определенный словарь эмоций и ассоциированных сценарных элементов остается без изменений...

def analyze_emotion(key_signature, dynamics, metronome_mark):
    """
    Расширенный анализ эмоций с учетом темпа.
    """
    if 'minor' in key_signature:
        emotion = 'sad'
    elif dynamics > 0.7:
        emotion = 'joyful'
    else:
        emotion = 'peaceful'
    
    # Учет темпа
    if metronome_mark:
        if metronome_mark.number > 120:
            emotion = 'joyful' if emotion == 'peaceful' else 'tense'
    
    return emotion

def extract_harmony(chord_element):
    """
    Анализирует аккорд и возвращает его гармоническую функцию.
    """
    root = chord_element.root()
    if chord_element.isDominantSeventh():
        return f"Dominant Seventh ({root})"
    elif chord_element.isDiminishedSeventh():
        return f"Diminished Seventh ({root})"
    elif chord_element.isMajorTriad():
        return f"Major Triad ({root})"
    elif chord_element.isMinorTriad():
        return f"Minor Triad ({root})"
    else:
        return f"Chord ({root})"

def extract_notes_and_chords(file_path):
    score = converter.parse(file_path)
    elements = []
    scenes = []
    emotion_counts = {'joyful': 0, 'tense': 0, 'sad': 0, 'peaceful': 0}
    
    for part_index, part in enumerate(score.parts):
        measure_number = 1
        for measure in part.getElementsByClass(stream.Measure):
            time_signature = measure.timeSignature
            key_signature = measure.keySignature
            metronome_mark = measure.metronomeMarkBoundaries()[0][2] if measure.metronomeMarkBoundaries() else None

            for element in measure.notesAndRests:
                dynamics = None  # Инициализация переменной
                element_info = {
                    'part_index': part_index + 1,
                    'type': '',
                    'pitch': '',
                    'duration': element.duration.quarterLength,
                    'offset': element.offset,
                    'measure': measure_number,
                    'time_signature': str(time_signature) if time_signature else None,
                    'key_signature': str(key_signature) if key_signature else None,
                    'dynamics': None,
                    'articulations': None,
                    'harmony': None
                }
                
                if not element.isRest:
                    if hasattr(element, 'volume') and element.volume.velocityScalar is not None:
                        dynamics = element.volume.velocityScalar
                        element_info['dynamics'] = dynamics
                    
                    if isinstance(element, note.Note):
                        element_info['type'] = 'note'
                        element_info['pitch'] = str(element.pitch)
                    elif isinstance(element, chord.Chord):
                        element_info['type'] = 'chord'
                        element_info['pitch'] = '+'.join(str(p) for p in element.pitches)
                        element_info['harmony'] = extract_harmony(element)
                
                elements.append(element_info)

                if dynamics is not None:
                    emotion = analyze_emotion(str(key_signature), dynamics, metronome_mark)
                    possible_scenes = emotion_to_scene.get(emotion, [])
                    scene_description = random.choice(possible_scenes) if possible_scenes else 'неопределенная сцена'
                    scenes.append((measure_number, emotion, scene_description))
                    emotion_counts[emotion] += 1
                
            measure_number += 1

    return elements, scenes, emotion_counts

def visualize_emotions(emotion_counts):
    plt.bar(emotion_counts.keys(), emotion_counts.values())
    plt.xlabel('Emotion')
    plt.ylabel('Count')
    plt.title('Emotion Distribution in Composition')
    plt.show()

# Пример использования функции
elements, scenes, emotion_counts = extract_notes_and_chords('C:/Users/ARTYOM/Documents/Python/Bring_it_up.musicxml')
for e in elements:
    print(e)

for measure_number, emotion, scene_description in scenes:
    print(f"Такт: {measure_number}, Эмоция: {emotion}, Предлагаемая сцена: {scene_description}")

visualize_emotions(emotion_counts)