// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Handles negotiating buffer sets with the codec server and sysmem.

use crate::{buffer_collection_constraints::*, Result};
use failure::{self, Fail, ResultExt};
use fidl::endpoints::{create_endpoints, ClientEnd};
use fidl_fuchsia_media::*;
use fidl_fuchsia_sysmem::*;
use fidl_table_validation::{ValidFidlTable, Validate};
use fuchsia_component::client;
use fuchsia_zircon as zx;
use std::{
    convert::TryFrom,
    fmt,
    iter::{IntoIterator, StepBy},
    ops::RangeFrom,
};

#[derive(Debug)]
pub enum Error {
    ReclaimClientTokenChannel,
    ServerOmittedBufferVmo,
    PacketReferencesInvalidBuffer,
    VmoReadFail(zx::Status),
}

impl fmt::Display for Error {
    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, w)
    }
}

impl Fail for Error {}

#[allow(unused)]
#[derive(ValidFidlTable, Copy, Clone, Debug, PartialEq)]
#[fidl_table_src(StreamBufferSettings)]
pub struct ValidStreamBufferSettings {
    buffer_lifetime_ordinal: u64,
    buffer_constraints_version_ordinal: u64,
    packet_count_for_server: u32,
    packet_count_for_client: u32,
    per_packet_buffer_bytes: u32,
    #[fidl_field_type(default = false)]
    single_buffer_mode: bool,
}

#[allow(unused)]
#[derive(ValidFidlTable)]
#[fidl_table_src(StreamBufferConstraints)]
#[fidl_table_validator(StreamBufferConstraintsValidator)]
pub struct ValidStreamBufferConstraints {
    buffer_constraints_version_ordinal: u64,
    default_settings: ValidStreamBufferSettings,
    per_packet_buffer_bytes_min: u32,
    per_packet_buffer_bytes_recommended: u32,
    per_packet_buffer_bytes_max: u32,
    packet_count_for_server_min: u32,
    packet_count_for_server_recommended: u32,
    packet_count_for_server_recommended_max: u32,
    packet_count_for_server_max: u32,
    packet_count_for_client_min: u32,
    packet_count_for_client_max: u32,
    single_buffer_mode_allowed: bool,
    #[fidl_field_type(default = false)]
    is_physically_contiguous_required: bool,
    #[fidl_field_type(optional)]
    very_temp_kludge_bti_handle: Option<zx::Handle>,
}

#[derive(ValidFidlTable)]
#[fidl_table_src(StreamOutputConstraints)]
pub struct ValidStreamOutputConstraints {
    pub stream_lifetime_ordinal: u64,
    pub buffer_constraints_action_required: bool,
    pub buffer_constraints: ValidStreamBufferConstraints,
}

pub struct StreamBufferConstraintsValidator;

#[derive(Debug)]
pub enum StreamBufferConstraintsError {
    VersionOrdinalZero,
    SingleBufferMode,
    ConstraintsNoBtiHandleForPhysicalBuffers,
}

impl Validate<ValidStreamBufferConstraints> for StreamBufferConstraintsValidator {
    type Error = StreamBufferConstraintsError;
    fn validate(candidate: &ValidStreamBufferConstraints) -> std::result::Result<(), Self::Error> {
        if candidate.buffer_constraints_version_ordinal == 0 {
            // An ordinal of 0 in StreamBufferConstraints is not allowed.
            return Err(StreamBufferConstraintsError::VersionOrdinalZero);
        }

        if candidate.default_settings.single_buffer_mode {
            // StreamBufferConstraints should never suggest single buffer mode.
            return Err(StreamBufferConstraintsError::SingleBufferMode);
        }

        if candidate.is_physically_contiguous_required
            && candidate
                .very_temp_kludge_bti_handle
                .as_ref()
                .map(|h| h.is_invalid())
                .unwrap_or(true)
        {
            // The bti handle must be provided if the buffers need to be physically contiguous.
            return Err(StreamBufferConstraintsError::ConstraintsNoBtiHandleForPhysicalBuffers);
        }

        Ok(())
    }
}

/// The pattern to use when advancing ordinals.
#[derive(Debug, Clone, Copy)]
pub enum OrdinalPattern {
    /// Odd ordinal pattern starts at 1 and moves in increments of 2: [1,3,5..]
    Odd,
    /// All ordinal pattern starts at 1 and moves in increments of 1: [1,2,3..]
    All,
}

impl IntoIterator for OrdinalPattern {
    type Item = u64;
    type IntoIter = StepBy<RangeFrom<Self::Item>>;
    fn into_iter(self) -> Self::IntoIter {
        let (start, step) = match self {
            OrdinalPattern::Odd => (1, 2),
            OrdinalPattern::All => (1, 1),
        };
        (start..).step_by(step)
    }
}

pub fn get_ordinal(pattern: &mut <OrdinalPattern as IntoIterator>::IntoIter) -> u64 {
    pattern.next().expect("Getting next item in infinite pattern")
}

pub enum BufferSetType {
    Input,
    Output,
}

pub struct BufferSetFactory;

impl BufferSetFactory {
    pub async fn buffer_set(
        buffer_lifetime_ordinal: u64,
        constraints: ValidStreamBufferConstraints,
        codec: &mut StreamProcessorProxy,
        buffer_set_type: BufferSetType,
        buffer_collection_constraints: Option<BufferCollectionConstraints>,
    ) -> Result<BufferSet> {
        let (collection_client, settings) = await!(Self::settings(
            buffer_lifetime_ordinal,
            constraints,
            buffer_collection_constraints
        ))?;

        vlog!(2, "Got settings; waiting for buffers.");

        match buffer_set_type {
            BufferSetType::Input => codec
                .set_input_buffer_partial_settings(settings)
                .context("Sending input partial settings to codec")?,
            BufferSetType::Output => codec
                .set_output_buffer_partial_settings(settings)
                .context("Sending output partial settings to codec")?,
        };

        let (status, collection_info) = await!(collection_client.wait_for_buffers_allocated())
            .context("Waiting for buffers")?;
        vlog!(2, "Sysmem responded: {:?}", status);
        let collection_info = zx::Status::ok(status).map(|_| collection_info)?;

        if let BufferSetType::Output = buffer_set_type {
            vlog!(2, "Completing settings for output.");
            codec.complete_output_buffer_partial_settings(buffer_lifetime_ordinal)?;
        }

        //collection_client.close()?;

        vlog!(
            2,
            "Got {} buffers of size {:?}",
            collection_info.buffer_count,
            collection_info.settings.buffer_settings.size_bytes
        );
        vlog!(3, "Buffer collection is: {:#?}", collection_info.settings);
        for (i, buffer) in collection_info.buffers.iter().enumerate() {
            // We enumerate beyond collection_info.buffer_count just for debugging
            // purposes at this log level.
            vlog!(3, "Buffer {} is : {:#?}", i, buffer);
        }

        Ok(BufferSet::try_from(BufferSetSpec {
            proxy: collection_client,
            buffer_lifetime_ordinal,
            collection_info,
        })?)
    }

    async fn settings(
        buffer_lifetime_ordinal: u64,
        constraints: ValidStreamBufferConstraints,
        buffer_collection_constraints: Option<BufferCollectionConstraints>,
    ) -> Result<(BufferCollectionProxy, StreamBufferPartialSettings)> {
        let (client_token, client_token_request) =
            create_endpoints::<BufferCollectionTokenMarker>()?;
        let (codec_token, codec_token_request) = create_endpoints::<BufferCollectionTokenMarker>()?;
        let client_token = client_token.into_proxy()?;

        let sysmem_client =
            client::connect_to_service::<AllocatorMarker>().context("Connecting to sysmem")?;

        sysmem_client
            .allocate_shared_collection(client_token_request)
            .context("Allocating shared collection")?;
        client_token.duplicate(std::u32::MAX, codec_token_request)?;

        let (collection_client, collection_request) = create_endpoints::<BufferCollectionMarker>()?;
        sysmem_client.bind_shared_collection(
            ClientEnd::new(
                client_token
                    .into_channel()
                    .map_err(|_| Error::ReclaimClientTokenChannel)?
                    .into_zx_channel(),
            ),
            collection_request,
        )?;
        let collection_client = collection_client.into_proxy()?;
        await!(collection_client.sync()).context("Syncing codec_token_request with sysmem")?;

        let mut collection_constraints =
            buffer_collection_constraints.unwrap_or(BUFFER_COLLECTION_CONSTRAINTS_DEFAULT);
        assert_eq!(
            collection_constraints.min_buffer_count_for_camping, 0,
            "Codecs assert that buffer_count == packet count, so we can't change this yet."
        );
        collection_constraints.min_buffer_count_for_camping =
            constraints.default_settings.packet_count_for_client;

        vlog!(3, "Our buffer collection constraints are: {:#?}", collection_constraints);

        // By design we must say true even if all our fields are left at
        // default, or sysmem will not give us buffer handles.
        let has_constraints = true;
        collection_client
            .set_constraints(has_constraints, &mut collection_constraints)
            .context("Sending buffer constraints to sysmem")?;

        Ok((
            collection_client,
            StreamBufferPartialSettings {
                buffer_lifetime_ordinal: Some(buffer_lifetime_ordinal),
                buffer_constraints_version_ordinal: Some(
                    constraints.buffer_constraints_version_ordinal,
                ),
                single_buffer_mode: Some(constraints.default_settings.single_buffer_mode),
                packet_count_for_server: Some(constraints.default_settings.packet_count_for_server),
                packet_count_for_client: Some(constraints.default_settings.packet_count_for_client),
                sysmem_token: Some(codec_token),
            },
        ))
    }
}

#[derive(ValidFidlTable, Clone, Copy, Debug, PartialEq)]
#[fidl_table_src(PacketHeader)]
pub struct ValidPacketHeader {
    pub buffer_lifetime_ordinal: u64,
    pub packet_index: u32,
}

#[derive(ValidFidlTable, Clone, Copy, Debug, PartialEq)]
#[fidl_table_src(Packet)]
pub struct ValidPacket {
    pub header: ValidPacketHeader,
    pub buffer_index: u32,
    pub stream_lifetime_ordinal: u64,
    pub start_offset: u32,
    pub valid_length_bytes: u32,
    #[fidl_field_type(optional)]
    pub timestamp_ish: Option<u64>,
    #[fidl_field_type(default = false)]
    pub start_access_unit: bool,
    #[fidl_field_type(default = false)]
    pub known_end_access_unit: bool,
}

struct BufferSetSpec {
    proxy: BufferCollectionProxy,
    buffer_lifetime_ordinal: u64,
    collection_info: BufferCollectionInfo2,
}

#[derive(Debug, PartialEq)]
pub struct Buffer {
    pub data: zx::Vmo,
    pub start: u64,
    pub size: u64,
}

#[derive(Debug)]
pub struct BufferSet {
    pub proxy: BufferCollectionProxy,
    pub buffers: Vec<Buffer>,
    pub buffer_lifetime_ordinal: u64,
}

impl TryFrom<BufferSetSpec> for BufferSet {
    type Error = failure::Error;
    fn try_from(mut src: BufferSetSpec) -> std::result::Result<Self, Self::Error> {
        let mut buffers = vec![];
        for (i, buffer) in src.collection_info.buffers
            [0..(src.collection_info.buffer_count as usize)]
            .iter_mut()
            .enumerate()
        {
            buffers.push(Buffer {
                data: buffer.vmo.take().ok_or(Error::ServerOmittedBufferVmo).context(format!(
                    "Trying to ingest {}th buffer of {}: {:#?}",
                    i, src.collection_info.buffer_count, buffer
                ))?,
                start: buffer.vmo_usable_start,
                size: src.collection_info.settings.buffer_settings.size_bytes as u64,
            });
        }

        Ok(Self { proxy: src.proxy, buffers, buffer_lifetime_ordinal: src.buffer_lifetime_ordinal })
    }
}

impl BufferSet {
    pub fn read_packet(&self, packet: &ValidPacket) -> Result<Vec<u8>> {
        let buffer = self
            .buffers
            .get(packet.buffer_index as usize)
            .ok_or(Error::PacketReferencesInvalidBuffer)?;
        let mut dest = vec![0; packet.valid_length_bytes as usize];
        buffer.data.read(&mut dest, packet.start_offset as u64).map_err(Error::VmoReadFail)?;
        Ok(dest)
    }
}
