#! /usr/bin/env python3
"""Provide SoundFile which is used to link between database and file system.

File name
=========
It tries to parse the file name to get the date of the diffusion of an
episode and associate the file with it; We use the following format:
    yyyymmdd[_n][_][name]

Where:
    'yyyy' the year of the episode's diffusion;
    'mm' the month of the episode's diffusion;
    'dd' the day of the episode's diffusion;
    'n' the number of the episode (if multiple episodes);
    'name' the title of the sound;

Sound Quality
=============
To check quality of files, call the command sound_quality_check using the
parameters given by the setting SOUND_QUALITY. This script requires
Sox (and soxi).
"""
import logging

from django.conf import settings as conf

from aircox.models import Program, Sound, EpisodeSound


logger = logging.getLogger("aircox.commands")


__all__ = ("SoundFile",)


class SoundFile:
    """Handle synchronisation between sounds on files and database."""

    path = None
    info = None
    path_info = None
    sound = None

    def __init__(self, path):
        self.path = path

    @property
    def sound_path(self):
        """Relative path name."""
        return self.path.replace(conf.MEDIA_ROOT + "/", "")

    @property
    def episode(self):
        return self.sound and self.sound.episode

    def sync(self, sound=None, program=None, deleted=False, keep_deleted=False, **kwargs):
        """Update related sound model and save it."""
        if deleted:
            self.sound = self._on_delete(self.path, keep_deleted)
            return self.sound

        program = sound and sound.program or Program.get_from_path(self.path)
        if program:
            kwargs["program_id"] = program.pk

        created = False
        if not sound:
            sound, created = Sound.objects.get_or_create(file=self.sound_path, defaults=kwargs)

        self.sound = sound
        sound.sync_fs(on_update=True, find_playlist=True)
        sound.save()

        if not sound.episodesound_set.all().exists():
            self.find_episode_sound(sound)
        return sound

    def find_episode_sound(self, sound):
        episode = sound.find_episode()
        if episode:
            # FIXME: position from name
            item = EpisodeSound(
                episode=episode, sound=sound, position=episode.episodesound_set.all().count(), broadcast=sound.broadcast
            )
            item.save()

    def _on_delete(self, path, keep_deleted):
        sound = None
        if keep_deleted:
            if sound := Sound.objects.path(self.path).first():
                sound.is_removed = True
                sound.save(sync=False)
        elif sound := Sound.objects.path(self.path):
            sound.delete()
        return sound
