//! A channel buffer as created through [Channels::channel][crate::Channels::channel] or
//! [ChannelsMut::channel_mut][crate::ChannelsMut::channel_mut].

use std::cmp;
use std::fmt;
use std::hash;

use crate::translate::Translate;
use std::ops;

mod iter;
pub use self::iter::{Iter, IterMut};

/// Used to determine how a buffer is indexed.
#[derive(Debug, Clone, Copy)]
enum Kind {
    /// Returned channel buffer is indexed in a linear manner.
    Linear,
    /// Returned channel buffer is indexed in an interleaved manner.
    Interleaved {
        /// The number of channels in the interleaved buffer.
        channels: usize,
        /// The channel that is being accessed.
        channel: usize,
    },
}

/// The buffer of a single channel.
///
/// This doesn't provide direct access to the underlying buffer, but rather
/// allows us to copy data usinga  number of utility functions.
///
/// See [Channels::channel][crate::Channels::channel].
pub struct Channel<'a, T> {
    buf: &'a [T],
    kind: Kind,
}

impl<'a, T> Channel<'a, T> {
    /// Construct a linear channel buffer.
    ///
    /// The buffer provided as-is constitutes the frames of the channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channel;
    ///
    /// let buf = &mut [1, 3, 5, 7];
    /// let channel = Channel::linear(buf);
    ///
    /// assert_eq!(channel[1], 3);
    /// assert_eq!(channel[2], 5);
    /// ```
    pub fn linear(buf: &'a [T]) -> Self {
        Self {
            buf,
            kind: Kind::Linear,
        }
    }

    /// Construct an interleaved channel buffer.
    ///
    /// The provided buffer must be the complete buffer, which includes *all*
    /// other channels. The provided `channels` argument is the total number of
    /// channels in this buffer, and `channel` indicates which specific channel
    /// this buffer belongs to.
    ///
    /// Note that this is typically not used directly, but instead through an
    /// abstraction which makes sure to provide the correct parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channel;
    ///
    /// let buf = &[1, 2, 3, 4, 5, 6, 7, 8];
    /// let channel = Channel::interleaved(buf, 2, 1);
    ///
    /// assert_eq!(channel[1], 4);
    /// assert_eq!(channel[2], 6);
    /// ```
    pub fn interleaved(buf: &'a [T], channels: usize, channel: usize) -> Self {
        Self {
            buf,
            kind: Kind::Interleaved { channels, channel },
        }
    }

    /// Access the number of frames on the current channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channels;
    ///
    /// fn test(buf: &dyn Channels<f32>) {
    ///     let left = buf.channel(0);
    ///     let right = buf.channel(1);
    ///
    ///     assert_eq!(left.frames(), 16);
    ///     assert_eq!(right.frames(), 16);
    /// }
    ///
    /// test(&audio::dynamic![[0.0; 16]; 2]);
    /// test(&audio::sequential![[0.0; 16]; 2]);
    /// test(&audio::interleaved![[0.0; 16]; 2]);
    /// ```
    pub fn frames(&self) -> usize {
        match self.kind {
            Kind::Linear => self.buf.len(),
            Kind::Interleaved { channels, .. } => self.buf.len() / channels,
        }
    }

    /// Construct an iterator over the channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let mut left = audio::interleaved![[0.0f32; 4]; 2];
    /// let mut right = audio::dynamic![[0.0f32; 4]; 2];
    ///
    /// for (l, r) in left.channel_mut(0).iter_mut().zip(right.channel_mut(0)) {
    ///     *l = 1.0;
    ///     *r = 1.0;
    /// }
    ///
    /// assert!(left.channel(0).iter().eq(right.channel(0).iter()));
    ///
    /// assert_eq!(left.as_slice(), &[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// assert_eq!(&right[0], &[1.0, 1.0, 1.0, 1.0]);
    /// assert_eq!(&right[1], &[0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn iter(self) -> Iter<'a, T> {
        match self.kind {
            Kind::Linear => Iter::new(self.buf, 1),
            Kind::Interleaved { channels, channel } => {
                let start = usize::min(channel, self.buf.len());
                Iter::new(&self.buf[start..], channels)
            }
        }
    }

    /// Construct a new [Channel] reference with a lifetime associated with the
    /// current channel instance instead of the underlying buffer.
    ///
    /// Most of the time it is not necessary to use this, since [Channel]
    /// implements [Copy] and its lifetime would coerce to any compatible
    /// lifetime. This method is currently just here for completeness sake.
    ///
    /// Both of these work equally well:
    ///
    /// ```rust
    /// use audio::Channel;
    ///
    /// struct Foo<'a> {
    ///     channel: Channel<'a, i16>,
    /// }
    ///
    /// impl<'a> Foo<'a> {
    ///     fn channel(&self) -> Channel<'_, i16> {
    ///         self.channel.as_ref()
    ///     }
    ///
    ///     fn coerced_channel(&self) -> Channel<'_, i16> {
    ///         self.channel
    ///     }
    /// }
    /// ```
    #[inline]
    pub fn as_ref(&self) -> Channel<'_, T> {
        Channel {
            buf: self.buf,
            kind: self.kind,
        }
    }

    /// Construct a channel buffer where the first `n` frames are skipped.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let mut from = audio::interleaved![[0.0f32; 4]; 2];
    /// *from.frame_mut(0, 2).unwrap() = 1.0;
    /// *from.frame_mut(0, 3).unwrap() = 1.0;
    ///
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).copy_from(from.channel(0).skip(2));
    /// assert_eq!(to.as_slice(), &[1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn skip(self, n: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Self {
                buf: buf.get(n..).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => Self {
                buf: buf.get(n * channels..).unwrap_or_default(),
                kind,
            },
        }
    }

    /// Construct a channel buffer where the last `n` frames are included.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::interleaved![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).as_mut().tail(2).copy_from(from.channel(0));
    /// assert_eq!(to.as_slice(), &[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// ```
    pub fn tail(self, n: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => {
                let start = buf.len().saturating_sub(n);

                Self {
                    buf: buf.get(start..).unwrap_or_default(),
                    kind,
                }
            }
            Kind::Interleaved { channels, .. } => {
                let start = buf.len().saturating_sub(n * channels);

                Self {
                    buf: buf.get(start..).unwrap_or_default(),
                    kind,
                }
            }
        }
    }

    /// Limit the channel bufferto `limit` number of frames.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::interleaved![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).copy_from(from.channel(0).limit(2));
    /// assert_eq!(to.as_slice(), &[1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn limit(self, limit: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Channel {
                buf: buf.get(..limit).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => Channel {
                buf: buf.get(..limit * channels).unwrap_or_default(),
                kind,
            },
        }
    }

    /// Construct a range of frames corresponds to the chunk with `len` and
    /// position `n`.
    ///
    /// Which is the range `n * len .. n * len + len`.
    pub fn chunk(self, n: usize, len: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Channel {
                buf: buf.get(n..n + len).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => {
                let len = len * channels;
                let n = n * len;

                Channel {
                    buf: buf.get(n..n + len).unwrap_or_default(),
                    kind,
                }
            }
        }
    }

    /// How many chunks of the given size can you divide buf into.
    ///
    /// This includes one extra chunk even if the chunk doesn't divide the frame
    /// length evenly.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channels;
    ///
    /// fn test(buf: &dyn Channels<f32>) {
    ///     let left = buf.channel(0);
    ///     let right = buf.channel(1);
    ///
    ///     assert_eq!(left.chunks(4), 4);
    ///     assert_eq!(right.chunks(4), 4);
    ///
    ///     assert_eq!(left.chunks(6), 3);
    ///     assert_eq!(right.chunks(6), 3);
    /// }
    ///
    /// test(&audio::dynamic![[0.0; 16]; 2]);
    /// test(&audio::sequential![[0.0; 16]; 2]);
    /// test(&audio::interleaved![[0.0; 16]; 2]);
    /// ```
    pub fn chunks(&self, chunk: usize) -> usize {
        let len = self.frames();

        if len % chunk == 0 {
            len / chunk
        } else {
            len / chunk + 1
        }
    }

    /// Copy into the given slice of output.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channels;
    ///
    /// fn test(buf: &dyn Channels<f32>) {
    ///     let channel = buf.channel(0);
    ///
    ///     let mut buf = vec![0.0; 16];
    ///     channel.copy_into_slice(&mut buf[..]);
    ///
    ///     assert!(buf.iter().all(|f| *f == 1.0));
    /// }
    ///
    /// test(&audio::dynamic![[1.0; 16]; 2]);
    /// test(&audio::sequential![[1.0; 16]; 2]);
    /// test(&audio::interleaved![[1.0; 16]; 2]);
    /// ```
    pub fn copy_into_slice(&self, out: &mut [T])
    where
        T: Copy,
    {
        match self.kind {
            Kind::Linear => {
                let end = usize::min(out.len(), self.buf.len());
                out[..end].copy_from_slice(&self.buf[..end]);
            }
            Kind::Interleaved { channels, channel } => {
                for (o, f) in out
                    .iter_mut()
                    .zip(self.buf[channel..].iter().step_by(channels))
                {
                    *o = *f;
                }
            }
        }
    }

    /// Copy into the given iterator.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channels;
    ///
    /// fn test(buf: &dyn Channels<f32>) {
    ///     let channel = buf.channel(0);
    ///
    ///     let mut buf = vec![0.0; 16];
    ///
    ///     // Copy into every other position in `buf`.
    ///     channel.copy_into_iter(buf.iter_mut().step_by(2));
    ///
    ///     for (n, f) in buf.into_iter().enumerate() {
    ///         if n % 2 == 0 {
    ///             assert_eq!(f, 1.0);
    ///         } else {
    ///             assert_eq!(f, 0.0);
    ///         }
    ///     }
    /// }
    ///
    /// test(&audio::dynamic![[1.0; 16]; 2]);
    /// test(&audio::sequential![[1.0; 16]; 2]);
    /// test(&audio::interleaved![[1.0; 16]; 2]);
    /// ```
    pub fn copy_into_iter<'out, I>(&self, iter: I)
    where
        I: IntoIterator<Item = &'out mut T>,
        T: 'out + Copy,
    {
        match self.kind {
            Kind::Linear => {
                for (o, f) in iter.into_iter().zip(self.buf) {
                    *o = *f;
                }
            }
            Kind::Interleaved { channels, channel } => {
                for (o, f) in iter
                    .into_iter()
                    .zip(self.buf[channel..].iter().step_by(channels))
                {
                    *o = *f;
                }
            }
        }
    }
}

impl<T> Clone for Channel<'_, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Copy for Channel<'_, T> {}

impl<T> fmt::Debug for Channel<'_, T>
where
    T: Copy + fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_list().entries(self.iter()).finish()
    }
}

impl<T> cmp::PartialEq for Channel<'_, T>
where
    T: Copy + cmp::PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.iter().eq(other.iter())
    }
}

impl<T> cmp::Eq for Channel<'_, T> where T: Copy + cmp::Eq {}

impl<T> cmp::PartialOrd for Channel<'_, T>
where
    T: Copy + cmp::PartialOrd,
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.iter().partial_cmp(other.iter())
    }
}

impl<T> cmp::Ord for Channel<'_, T>
where
    T: Copy + cmp::Ord,
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.iter().cmp(other.iter())
    }
}

impl<T> hash::Hash for Channel<'_, T>
where
    T: Copy + hash::Hash,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: hash::Hasher,
    {
        for f in self.iter() {
            f.hash(state);
        }
    }
}

impl<'a, T> IntoIterator for Channel<'a, T>
where
    T: Copy,
{
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a Channel<'_, T>
where
    T: Copy,
{
    type Item = T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.as_ref().iter()
    }
}

impl<T> ops::Index<usize> for Channel<'_, T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        match self.kind {
            Kind::Linear => &self.buf[index],
            Kind::Interleaved { channels, channel } => &self.buf[channel + channels * index],
        }
    }
}

/// The mutable buffer of a single channel.
///
/// This doesn't provide direct access to the underlying buffer, but rather
/// allows us to copy data usinga  number of utility functions.
///
/// See [ChannelsMut::channel_mut][crate::ChannelsMut::channel_mut].
pub struct ChannelMut<'a, T> {
    buf: &'a mut [T],
    kind: Kind,
}

impl<'a, T> ChannelMut<'a, T> {
    /// Construct a mutable linear channel buffer.
    ///
    /// The buffer provided as-is constitutes the frames of the channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelMut;
    ///
    /// let buf = &mut [1, 3, 5, 7];
    /// let mut channel = ChannelMut::linear(buf);
    ///
    /// assert_eq!(channel[1], 3);
    /// assert_eq!(channel[2], 5);
    ///
    /// channel[1] *= 4;
    ///
    /// assert_eq!(buf, &[1, 12, 5, 7]);
    /// ```
    pub fn linear(buf: &'a mut [T]) -> Self {
        Self {
            buf,
            kind: Kind::Linear,
        }
    }

    /// Construct a mutable interleaved channel buffer.
    ///
    /// The provided buffer must be the complete buffer, which includes *all*
    /// other channels. The provided `channels` argument is the total number of
    /// channels in this buffer, and `channel` indicates which specific channel
    /// this buffer belongs to.
    ///
    /// Note that this is typically not used directly, but instead through an
    /// abstraction which makes sure to provide the correct parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelMut;
    ///
    /// let buf = &mut [1, 2, 3, 4, 5, 6, 7, 8];
    /// let mut channel = ChannelMut::interleaved(buf, 2, 1);
    ///
    /// assert_eq!(channel[1], 4);
    /// assert_eq!(channel[2], 6);
    ///
    /// channel[1] *= 4;
    ///
    /// assert_eq!(buf, &[1, 2, 3, 16, 5, 6, 7, 8]);
    /// ```
    pub fn interleaved(buf: &'a mut [T], channels: usize, channel: usize) -> Self {
        Self {
            buf,
            kind: Kind::Interleaved { channels, channel },
        }
    }

    /// Convert the current mutable channel into a [Channel] with the lifetime
    /// matching the underlying buffer.
    ///
    /// This is required in order to fully convert a [ChannelMut] into a
    /// [Channel] with the lifetime associated with the buffer, because if we
    /// only use [as_ref][ChannelMut::as_ref] we'll actually be creating a
    /// reference to the mutable buffer instead.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channel, ChannelMut};
    ///
    /// struct Foo<'a> {
    ///     channel: ChannelMut<'a, i16>,
    /// }
    ///
    /// impl<'a> Foo<'a> {
    ///     fn into_channel(self) -> Channel<'a, i16> {
    ///         self.channel.into_ref()
    ///     }
    /// }
    /// ```
    ///
    /// In contrast, this doesn't compile:
    ///
    /// ```rust,compile_fail
    /// use audio::{Channel, ChannelMut};
    ///
    /// struct Foo<'a> {
    ///     channel: ChannelMut<'a, i16>,
    /// }
    ///
    /// impl<'a> Foo<'a> {
    ///     fn into_channel(self) -> Channel<'a, i16> {
    ///         self.channel.as_ref()
    ///     }
    /// }
    /// ```
    ///
    /// With the following error:
    ///
    /// ```text
    ///    error[E0515]: cannot return value referencing local data `self.channel`
    ///    --> test.rs:11:9
    ///     |
    ///  11 |         self.channel.as_ref()
    ///     |         ------------^^^^^^^^^
    ///     |         |
    ///     |         returns a value referencing data owned by the current function
    ///     |         `self.channel` is borrowed here
    ///```
    #[inline]
    pub fn into_ref(self) -> Channel<'a, T> {
        Channel {
            buf: self.buf,
            kind: self.kind,
        }
    }

    /// Construct a new [Channel] reference with a lifetime associated with the
    /// current channel instance instead of the underlying buffer.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channel, ChannelMut};
    ///
    /// let buf = &mut [1, 2, 3, 4];
    /// let channel = ChannelMut::linear(buf);
    ///
    /// let channel1 = channel.as_ref();
    /// let channel2 = channel1; // Channel is Copy.
    ///
    /// assert_eq!(channel1[0], channel2[0]);
    /// ```
    #[inline]
    pub fn as_ref(&self) -> Channel<'_, T> {
        Channel {
            buf: self.buf,
            kind: self.kind,
        }
    }

    /// Construct a new mutable channel reference with a lifetime associated
    /// with the current channel instance instead of the underlying buffer.
    ///
    /// Reborrowing like this is sometimes necessary, like if you want to pass
    /// an instance of [ChannelMut] directly into another function instead of
    /// borrowing it:
    ///
    /// ```rust
    /// use audio::{ChannelsMut, ChannelMut};
    ///
    /// fn takes_channel_mut(mut channel: ChannelMut<'_, i16>) {
    ///     channel[1] = 42;
    /// }
    ///
    /// let mut buffer = audio::interleaved![[0; 4]; 2];
    /// let mut channel = buffer.channel_mut(1);
    ///
    /// takes_channel_mut(channel.as_mut());
    ///
    /// assert_eq!(channel[1], 42);
    /// ```
    ///
    /// Without the reborrow, we would end up moving the channel:
    ///
    /// ```rust,compile_fail
    /// use audio::{ChannelsMut, ChannelMut};
    ///
    /// fn takes_channel_mut(mut channel: ChannelMut<'_, i16>) {
    ///     channel[1] = 42;
    /// }
    ///
    /// let mut buffer = audio::interleaved![[0; 4]; 2];
    /// let mut channel = buffer.channel_mut(1);
    ///
    /// takes_channel_mut(channel);
    ///
    /// assert_eq!(channel[1], 42);
    /// ```
    ///
    /// Causing the following error:
    ///
    /// ```text
    ///    error[E0382]: borrow of moved value: `channel`
    ///    --> test.rs:10:12
    ///     |
    ///  10 | let mut channel = buffer.channel_mut(1);
    ///     |     ----------- move occurs because `channel` has type `ChannelMut<'_, i16>`,
    ///     |                 which does not implement the `Copy` trait
    ///  11 |
    ///  12 | takes_channel_mut(channel);
    ///     |                   ------- value moved here
    ///  13 |
    ///  14 | assert_eq!(channel[1], 42);
    ///     |            ^^^^^^^ value borrowed here after move
    /// ```
    #[inline]
    pub fn as_mut(&mut self) -> ChannelMut<'_, T> {
        ChannelMut {
            buf: self.buf,
            kind: self.kind,
        }
    }

    /// The number of frames in the buffer.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelsMut;
    ///
    /// fn test(buf: &dyn ChannelsMut<f32>) {
    ///     let left = buf.channel(0);
    ///     let right = buf.channel(1);
    ///
    ///     assert_eq!(left.frames(), 16);
    ///     assert_eq!(right.frames(), 16);
    /// }
    ///
    /// test(&audio::dynamic![[0.0; 16]; 2]);
    /// test(&audio::sequential![[0.0; 16]; 2]);
    /// test(&audio::interleaved![[0.0; 16]; 2]);
    /// ```
    pub fn frames(&self) -> usize {
        match self.kind {
            Kind::Linear => self.buf.len(),
            Kind::Interleaved { channels, .. } => self.buf.len() / channels,
        }
    }

    /// The number of chunks that can fit with the given size.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelsMut;
    ///
    /// fn test(buf: &dyn ChannelsMut<f32>) {
    ///     let left = buf.channel(0);
    ///     let right = buf.channel(1);
    ///
    ///     assert_eq!(left.chunks(4), 4);
    ///     assert_eq!(right.chunks(4), 4);
    ///
    ///     assert_eq!(left.chunks(6), 3);
    ///     assert_eq!(right.chunks(6), 3);
    /// }
    ///
    /// test(&audio::dynamic![[0.0; 16]; 2]);
    /// test(&audio::sequential![[0.0; 16]; 2]);
    /// test(&audio::interleaved![[0.0; 16]; 2]);
    /// ```
    pub fn chunks(&self, chunk: usize) -> usize {
        let len = self.frames();

        if len % chunk == 0 {
            len / chunk
        } else {
            len / chunk + 1
        }
    }

    /// Construct an iterator over the channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let mut left = audio::interleaved![[0.0f32; 4]; 2];
    /// let mut right = audio::dynamic![[0.0f32; 4]; 2];
    ///
    /// for (l, r) in left.channel_mut(0).iter_mut().zip(right.channel_mut(0)) {
    ///     *l = 1.0;
    ///     *r = 1.0;
    /// }
    ///
    /// assert!(left.channel(0).iter().eq(right.channel(0).iter()));
    ///
    /// assert_eq!(left.as_slice(), &[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// assert_eq!(&right[0], &[1.0, 1.0, 1.0, 1.0]);
    /// assert_eq!(&right[1], &[0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn iter(self) -> Iter<'a, T> {
        self.into_ref().iter()
    }

    /// Construct a mutable iterator over the channel.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let mut left = audio::interleaved![[0.0f32; 4]; 2];
    /// let mut right = audio::dynamic![[0.0f32; 4]; 2];
    ///
    /// for (l, r) in left.channel_mut(0).iter_mut().zip(right.channel_mut(0)) {
    ///     *l = 1.0;
    ///     *r = 1.0;
    /// }
    ///
    /// assert!(left.channel(0).iter().eq(right.channel(0).iter()));
    ///
    /// assert_eq!(left.as_slice(), &[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// assert_eq!(&right[0], &[1.0, 1.0, 1.0, 1.0]);
    /// assert_eq!(&right[1], &[0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn iter_mut(self) -> IterMut<'a, T> {
        match self.kind {
            Kind::Linear => IterMut::new(self.buf, 1),
            Kind::Interleaved { channels, channel } => {
                let start = usize::min(channel, self.buf.len());
                IterMut::new(&mut self.buf[start..], channels)
            }
        }
    }

    /// Construct a channel buffer where the first `n` frames are skipped.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let mut buffer = audio::Interleaved::with_topology(2, 4);
    ///
    /// buffer.channel_mut(0).skip(2).copy_from_slice(&[1.0, 1.0]);
    ///
    /// assert_eq!(buffer.as_slice(), &[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0])
    /// ```
    pub fn skip(self, n: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Self {
                buf: buf.get_mut(n..).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => Self {
                buf: buf.get_mut(n * channels..).unwrap_or_default(),
                kind,
            },
        }
    }

    /// Construct a channel buffer where the last `n` frames are included.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::interleaved![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).as_mut().tail(2).copy_from(from.channel(0));
    /// assert_eq!(to.as_slice(), &[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// ```
    pub fn tail(self, n: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => {
                let start = buf.len().saturating_sub(n);

                Self {
                    buf: buf.get_mut(start..).unwrap_or_default(),
                    kind,
                }
            }
            Kind::Interleaved { channels, .. } => {
                let start = buf.len().saturating_sub(n * channels);

                Self {
                    buf: buf.get_mut(start..).unwrap_or_default(),
                    kind,
                }
            }
        }
    }

    /// Limit the channel bufferto `limit` number of frames.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::interleaved![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).limit(2).copy_from(from.channel(0));
    /// assert_eq!(to.as_slice(), &[1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
    /// ```
    pub fn limit(self, limit: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Self {
                buf: buf.get_mut(..limit).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => Self {
                buf: buf.get_mut(..limit * channels).unwrap_or_default(),
                kind,
            },
        }
    }

    /// Construct a range of frames corresponds to the chunk with `len` and
    /// position `n`.
    ///
    /// Which is the range `n * len .. n * len + len`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::interleaved![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 2];
    ///
    /// to.channel_mut(0).chunk(1, 2).copy_from(from.channel(0));
    /// assert_eq!(to.as_slice(), &[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0]);
    /// ```
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::Channels;
    ///
    /// fn test(buf: &dyn Channels<f32>) {
    ///     let channel = buf.channel(0);
    ///
    ///     let mut buf = vec![0.0; 4];
    ///     channel.chunk(3, 4).copy_into_slice(&mut buf[..]);
    ///
    ///     assert!(buf.iter().all(|f| *f == 1.0));
    /// }
    ///
    /// test(&audio::dynamic![[1.0; 16]; 2]);
    /// test(&audio::sequential![[1.0; 16]; 2]);
    /// test(&audio::interleaved![[1.0; 16]; 2]);
    /// ```
    pub fn chunk(self, n: usize, len: usize) -> Self {
        let Self { buf, kind } = self;

        match kind {
            Kind::Linear => Self {
                buf: buf.get_mut(n..n + len).unwrap_or_default(),
                kind,
            },
            Kind::Interleaved { channels, .. } => {
                let len = len * channels;
                let n = n * len;

                Self {
                    buf: buf.get_mut(n..n + len).unwrap_or_default(),
                    kind,
                }
            }
        }
    }

    /// Copy from the given slice.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelsMut;
    ///
    /// fn test(buf: &mut dyn ChannelsMut<f32>) {
    ///     buf.channel_mut(0).copy_from_slice(&[1.0; 4][..]);
    ///
    ///     let mut out = vec![0.0; 8];
    ///     buf.channel(0).copy_into_slice(&mut out);
    ///
    ///     assert_eq!(out, vec![1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]);
    /// }
    ///
    /// test(&mut audio::dynamic![[0.0; 8]; 2]);
    /// test(&mut audio::sequential![[0.0; 8]; 2]);
    /// test(&mut audio::interleaved![[0.0; 8]; 2]);
    /// ```
    pub fn copy_from_slice(&mut self, buf: &[T])
    where
        T: Copy,
    {
        match self.kind {
            Kind::Linear => {
                let len = usize::min(self.buf.len(), buf.len());
                self.buf[..len].copy_from_slice(&buf[..len]);
            }
            Kind::Interleaved { channels, channel } => {
                for (o, f) in self.buf[channel..].iter_mut().step_by(channels).zip(buf) {
                    *o = *f;
                }
            }
        }
    }

    /// Copy a chunked destination from an iterator.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::ChannelsMut;
    ///
    /// fn test(buf: &mut dyn ChannelsMut<f32>) {
    ///     buf.channel_mut(0).skip(2).copy_from_iter(vec![1.0; 4]);
    ///
    ///     let mut out = vec![0.0; 8];
    ///     buf.channel(0).copy_into_slice(&mut out);
    ///
    ///     assert_eq!(out, vec![0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0]);
    /// }
    ///
    /// test(&mut audio::dynamic![[0.0; 8]; 2]);
    /// test(&mut audio::sequential![[0.0; 8]; 2]);
    /// test(&mut audio::interleaved![[0.0; 8]; 2]);
    /// ```
    ///
    /// ```rust
    /// use audio::ChannelsMut;
    ///
    /// fn test(buf: &mut dyn ChannelsMut<f32>) {
    ///     buf.channel_mut(0).skip(2).chunk(0, 2).copy_from_iter(vec![1.0; 4]);
    ///
    ///     let mut out = vec![0.0; 8];
    ///     buf.channel(0).copy_into_slice(&mut out);
    ///
    ///     assert_eq!(out, vec![0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]);
    /// }
    ///
    /// test(&mut audio::dynamic![[0.0; 8]; 2]);
    /// test(&mut audio::sequential![[0.0; 8]; 2]);
    /// test(&mut audio::interleaved![[0.0; 8]; 2]);
    /// ```
    pub fn copy_from_iter<I>(&mut self, iter: I)
    where
        I: IntoIterator<Item = T>,
    {
        match self.kind {
            Kind::Linear => {
                for (o, f) in self.buf.iter_mut().zip(iter) {
                    *o = f;
                }
            }
            Kind::Interleaved { channels, channel } => {
                let buf = self.buf[channel..].iter_mut().step_by(channels);

                for (o, f) in buf.zip(iter) {
                    *o = f;
                }
            }
        }
    }

    /// Copy this channel from another.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::dynamic![[1.0f32; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 3];
    ///
    /// to.channel_mut(0).copy_from(from.channel(1));
    /// assert_eq!(to.as_slice(), &[1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
    /// ```
    pub fn copy_from(&mut self, from: Channel<'_, T>)
    where
        T: Copy,
    {
        match (self.kind, from.kind) {
            (Kind::Linear, Kind::Linear) => {
                let end = usize::min(self.buf.len(), from.buf.len());
                self.buf[..end].copy_from_slice(&from.buf[..end]);
            }
            _ => {
                for (o, f) in self.as_mut().iter_mut().zip(from) {
                    *o = f;
                }
            }
        }
    }

    /// Translate this channel from another.
    ///
    /// This will translate each sample in the channel through the appropriate
    /// [Translate] implementation.
    ///
    /// This is used for converting a buffer containing one type of sample into
    /// another.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use audio::{Channels as _, ChannelsMut as _};
    ///
    /// let from = audio::dynamic![[u16::MAX; 4]; 2];
    /// let mut to = audio::interleaved![[0.0f32; 4]; 3];
    ///
    /// to.channel_mut(0).translate_from(from.channel(1));
    /// assert_eq!(to.as_slice(), &[1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
    /// ```
    pub fn translate_from<U>(&mut self, from: Channel<'_, U>)
    where
        U: Copy,
        T: Translate<U>,
    {
        for (o, f) in self.as_mut().iter_mut().zip(from) {
            *o = T::translate(f);
        }
    }
}

impl<T> fmt::Debug for ChannelMut<'_, T>
where
    T: Copy + fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_list().entries(self.as_ref().iter()).finish()
    }
}

impl<T> cmp::PartialEq for ChannelMut<'_, T>
where
    T: Copy + cmp::PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.as_ref().iter().eq(other.as_ref().iter())
    }
}

impl<T> cmp::Eq for ChannelMut<'_, T> where T: Copy + cmp::Eq {}

impl<T> cmp::PartialOrd for ChannelMut<'_, T>
where
    T: Copy + cmp::PartialOrd,
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.as_ref().iter().partial_cmp(other.as_ref().iter())
    }
}

impl<T> cmp::Ord for ChannelMut<'_, T>
where
    T: Copy + cmp::Ord,
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.as_ref().iter().cmp(other.as_ref().iter())
    }
}

impl<T> hash::Hash for ChannelMut<'_, T>
where
    T: Copy + hash::Hash,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: hash::Hasher,
    {
        for f in self.as_ref().iter() {
            f.hash(state);
        }
    }
}

impl<'a, T> IntoIterator for ChannelMut<'a, T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

impl<'a, T> IntoIterator for &'a mut ChannelMut<'_, T> {
    type Item = &'a mut T;
    type IntoIter = IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.as_mut().iter_mut()
    }
}

impl<T> ops::Index<usize> for ChannelMut<'_, T> {
    type Output = T;

    fn index(&self, index: usize) -> &Self::Output {
        match self.kind {
            Kind::Linear => &self.buf[index],
            Kind::Interleaved { channels, channel } => &self.buf[channel + channels * index],
        }
    }
}

/// Get a mutable reference to the frame at the given index.
///
/// # Panics
///
/// Panics if the given frame is out of bounds for this channel.
///
/// See [frames][Self::frames].
///
/// # Examples
///
/// ```rust
/// use audio::ChannelsMut;
///
/// fn test(buf: &mut dyn ChannelsMut<f32>) {
///     buf.channel_mut(0)[1] = 1.0;
///     buf.channel_mut(0)[7] = 1.0;
///
///     let mut out = vec![0.0; 8];
///     buf.channel(0).copy_into_slice(&mut out);
///
///     assert_eq!(out, vec![0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]);
/// }
///
/// test(&mut audio::dynamic![[0.0; 8]; 2]);
/// test(&mut audio::sequential![[0.0; 8]; 2]);
/// test(&mut audio::interleaved![[0.0; 8]; 2]);
/// ```
impl<T> ops::IndexMut<usize> for ChannelMut<'_, T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        match self.kind {
            Kind::Linear => &mut self.buf[index],
            Kind::Interleaved { channels, channel } => &mut self.buf[channel + channels * index],
        }
    }
}
