import os
import pathlib

from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
from fastapi.testclient import TestClient
from AccelBrainBeat.brainbeat.binaural_beat import BinauralBeat
import pydub
import random

from animate_fractal import animategif
from blend_av import blend_av

app = FastAPI()


class App(BaseModel):
    app: str


class AudioProperties(BaseModel):
    """
    Audio properties
    """
    main_frequency: int
    lag_frequency: int
    volume: float
    breath_pattern_in: int
    breath_pattern_out: int
    bell_sound: str


class VideoProperties(BaseModel):
    """
    Video properties
    """
    main_frequency: int
    breath_pattern_in: int
    breath_pattern_out: int
    color_scheme = str


class AvProperties(BaseModel):
    """
    Audio and video properties
    """
    main_frequency: int
    lag_frequency: int
    volume: float
    breath_pattern_in: int
    breath_pattern_out: int
    bell_sound: str
    color_palette = str


@app.get("/")
async def get_root():
    appresponse = App(app='breathaudio')
    return appresponse


@app.get("/generate_audio")
async def get_generate_audio(audio_properties: AudioProperties):
    """
    Generate audio
    :param audio_properties:
    :return:
    """
    tmp_dir = pathlib.Path("tmp_sound")
    tmp_dir.mkdir(parents=True, exist_ok=True)
    # Remove existing files in tmp_dir
    for filename in os.listdir(tmp_dir):
        os.remove(tmp_dir / str(filename))
    bell_dir = pathlib.Path("bell")
    filename_prefix = ''.join([random.choice('0123456789ABCDEF') for i in range(32)])
    filename = f"{filename_prefix}.wav"
    # Generate binaural beat
    b = BinauralBeat()
    b.save_beat(output_file_name=str(tmp_dir / "binaural_beat.wav"),
                frequencys=(audio_properties.main_frequency,
                            audio_properties.lag_frequency),
                play_time=(audio_properties.breath_pattern_in + audio_properties.breath_pattern_out) * 2,
                volume=audio_properties.volume
                )
    pydub_background = pydub.AudioSegment.from_wav(tmp_dir / "binaural_beat.wav")
    bell_file = ""
    if audio_properties.bell_sound == "Cloche":
        bell_file = "339810__inspectorj__hand-bells-a-single-mod.wav"
        skip_bell = False
    elif audio_properties.bell_sound == "Bol tibétain":
        bell_file = "417116__dersinnsspace__tibetan-bowl_right-hit-mod.wav"
        skip_bell = False
    else:
        skip_bell = True
    if skip_bell:
        pydub_mix = pydub_background
    else:
        pydub_bell = pydub.AudioSegment.from_wav(bell_dir / bell_file)
        pydub_mix = pydub_background. \
            overlay(pydub_bell, position=0). \
            overlay(pydub_bell, position=audio_properties.breath_pattern_in * 1000). \
            overlay(pydub_bell,
                    position=(audio_properties.breath_pattern_in + audio_properties.breath_pattern_out) * 1000). \
            overlay(pydub_bell,
                    position=(audio_properties.breath_pattern_in * 2 + audio_properties.breath_pattern_out) * 1000)
    pydub_mix.export(tmp_dir / filename, format="wav")
    return FileResponse(tmp_dir / filename)


@app.get("/generate_video")
async def get_generate_video(video_properties: VideoProperties):
    """
    Generate video
    :param video_properties:
    :return:
    """
    tmp_dir = pathlib.Path("tmp_video")
    tmp_dir.mkdir(parents=True, exist_ok=True)
    # Remove existing files in tmp_dir
    for filename in os.listdir(tmp_dir):
        os.remove(tmp_dir / str(filename))
    anim = animategif()
    filename_prefix = ''.join([random.choice('0123456789ABCDEF') for i in range(32)])
    filename = f"{filename_prefix}.gif"
    anim.save(str(tmp_dir / filename), writer='imagemagick')
    return FileResponse(str(tmp_dir / filename))


@app.get("/generate_av")
async def get_generate_av(av_properties: AvProperties):
    """
    Generate audio and video using blend_av
    :param av_properties:
    :return:
    """

    a = AudioProperties()
    a.main_frequency = av_properties.main_frequency
    a.breath_pattern_in = av_properties.breath_pattern_in
    a.breath_pattern_out = av_properties.breath_pattern_out
    a.bell_sound = av_properties.bell_sound
    audio = get_generate_audio(a)

    v = VideoProperties()
    v.main_frequency = av_properties.main_frequency
    v.breath_pattern_in = av_properties.breath_pattern_in
    v.breath_pattern_out = av_properties.breath_pattern_out
    v.color_palette = av_properties.color_palette
    video = get_generate_video(v)

    av = blend_av(audio, video)
    return FileResponse(av)


client = TestClient(app)


def test_getroot():
    response = client.get("/")
    assert response.status_code == 200
