// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2024 Mike Robeson [dijksterhuis]

// non-functional

use std::path::Path;
use std::path::PathBuf;

use crate::sample_files::LazySampleFilePair;
use crate::sample_files::LazySampleFilePairs;
use crate::R;

#[derive(Clone, PartialEq, Debug, Copy)]
pub enum SamplePoolType {
    Audio,
    Project,
}

#[derive(Clone, PartialEq, Debug)]
pub struct SamplePool {
    dirpath: PathBuf,
    pool_type: SamplePoolType,
    files: LazySampleFilePairs,
}

impl SamplePool {
    pub fn path(&self) -> &Path {
        &self.dirpath
    }

    pub fn pathbuf(self) -> PathBuf {
        self.dirpath
    }

    pub fn pool_type(self) -> SamplePoolType {
        self.pool_type
    }

    pub fn pool_type_ref(&self) -> &SamplePoolType {
        &self.pool_type
    }

    pub fn files(self) -> LazySampleFilePairs {
        self.files
    }

    pub fn files_ref(&self) -> &LazySampleFilePairs {
        &self.files
    }

    pub fn files_mut(&mut self) -> &mut LazySampleFilePairs {
        &mut self.files
    }

    pub fn new(
        dirpath: PathBuf,
        pool_type: SamplePoolType,
    ) -> Self {
        Self {
            dirpath,
            pool_type,
            files: LazySampleFilePairs::new(),
        }
    }

    pub fn to_new(&self) -> Self {
        self.clone()
    }

    pub fn load(
        dirpath: PathBuf,
        pool_type: SamplePoolType,
    ) -> R<Self> {
        let files = LazySampleFilePairs::load(&dirpath)?;
        Ok(Self {
            dirpath,
            pool_type,
            files,
        })
    }

    pub fn push(
        &mut self,
        file: &mut LazySampleFilePair,
    ) -> R<()> {
        let audio_fname = file.audio_file_ref().path().file_name().unwrap();
        let new_audio_path = self.path().to_path_buf().join(audio_fname);
        let x = file.to_new(&new_audio_path)?;
        self.files.push(x);
        Ok(())
    }

    pub fn append(
        &mut self,
        files: &mut LazySampleFilePairs,
    ) -> R<()> {
        for f in files.iter_mut() {
            self.push(f)?;
        }
        Ok(())
    }

    // /// remove files from the given pool if they are not used
    // // todo: naming
    // pub fn delete_files(&mut self, paths_to_keep: &[PathBuf]) -> R<()> {
    //     let mut abs_paths_to_keep = Vec::<PathBuf>::new();
    //     for path in paths_to_keep {
    //         abs_paths_to_keep.push(path.canonicalize()?);
    //     }
    //
    //     for f in self.files_mut().iter_mut() {
    //         let path = f.audio_file_ref().pathbuf().canonicalize()?;
    //         if !abs_paths_to_keep.contains(&path) {
    //             f.set_delete_audio_file();
    //             f.set_delete_settings_file();
    //         }
    //     }
    //
    //     Ok(())
    // }

    pub fn commit(&mut self) -> R<()> {
        for f in self.files_mut().iter_mut() {
            f.commit()?;
        }
        Ok(())
    }
}

/// Both sample pools that can be accessed in a project.
///
/// ### WARNING
///
/// Loading multiple Projects that are members of the same Set means you can
/// edit audio pool files concurrently in different Projects! Ensure you write
/// changes to the filesystem appropriately.
#[derive(Clone, Debug)]
pub struct ProjectSamplePools {
    audio: SamplePool,
    project: SamplePool,
}

impl ProjectSamplePools {
    pub fn new(
        project_pool_dirpath: PathBuf,
        audio_pool_dirpath: PathBuf,
    ) -> Self {
        Self {
            audio: SamplePool::new(audio_pool_dirpath, SamplePoolType::Audio),
            project: SamplePool::new(project_pool_dirpath, SamplePoolType::Project),
        }
    }

    pub fn load(
        project_pool_dirpath: PathBuf,
        audio_pool_dirpath: PathBuf,
    ) -> R<Self> {
        let audio = SamplePool::load(audio_pool_dirpath, SamplePoolType::Audio)?;
        let project = SamplePool::load(project_pool_dirpath, SamplePoolType::Project)?;

        Ok(Self { audio, project })
    }

    pub fn audio(self) -> SamplePool {
        self.audio
    }

    pub fn audio_ref(&self) -> &SamplePool {
        &self.audio
    }

    pub fn audio_mut(&mut self) -> &mut SamplePool {
        &mut self.audio
    }

    pub fn project(self) -> SamplePool {
        self.project
    }

    pub fn project_ref(&self) -> &SamplePool {
        &self.project
    }

    pub fn project_mut(&mut self) -> &mut SamplePool {
        &mut self.project
    }
}
