// Copyright 2017 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.

#include "wav-source.h"

#include <fcntl.h>
#include <stdio.h>

#include <zircon/assert.h>
#include <fbl/auto_call.h>
#include <fbl/algorithm.h>
#include <lib/fdio/io.h>

zx_status_t WAVSource::Initialize(const char* filename) {
    zx_status_t res = WAVCommon::Initialize(filename, InitMode::SOURCE);
    if (res != ZX_OK) return res;

    RIFFChunkHeader riff_hdr;
    WAVHeader wav_info;

    auto cleanup = fbl::MakeAutoCall([&]() {
            Close();
            payload_len_ = 0;
        });

    // Read and sanity check the top level RIFF header
    res = Read(&riff_hdr, sizeof(riff_hdr));
    if (res != ZX_OK) {
        printf("Failed to read top level RIFF header!\n");
        return res;
    }
    riff_hdr.FixupEndian();

    if (riff_hdr.four_cc != RIFF_FOUR_CC) {
        printf("Missing expected 'RIFF' 4CC (expected 0x%08x got 0x%08x)\n",
               RIFF_FOUR_CC, riff_hdr.four_cc);
        return ZX_ERR_INVALID_ARGS;
    }

    // Read the WAVE header along with its required format chunk.
    res = Read(&wav_info, sizeof(wav_info));
    if (res != ZX_OK) {
        printf("Failed to read top level WAVE header!\n");
        return res;
    }
    wav_info.FixupEndian();

    if (wav_info.wave_four_cc != WAVE_FOUR_CC) {
        printf("Missing expected 'RIFF' 4CC (expected 0x%08x got 0x%08x)\n",
               WAVE_FOUR_CC, wav_info.wave_four_cc);
        return ZX_ERR_INVALID_ARGS;
    }

    if (wav_info.fmt_four_cc != FMT_FOUR_CC) {
        printf("Missing expected 'RIFF' 4CC (expected 0x%08x got 0x%08x)\n",
               FMT_FOUR_CC, wav_info.fmt_four_cc);
        return ZX_ERR_INVALID_ARGS;
    }

    if (!wav_info.frame_size) {
        printf("Bad frame size (%hu)\n", wav_info.frame_size);
        return ZX_ERR_INVALID_ARGS;
    }

    // Sanity check the format of the wave file.  This test app only supports a
    // limited subset of the possible formats.
    if (wav_info.format != FORMAT_LPCM) {
        printf("Unsupported format (0x%08hx) must be LPCM (0x%08hx)\n",
                wav_info.format, FORMAT_LPCM);
        return ZX_ERR_INVALID_ARGS;
    }

    switch (wav_info.bits_per_sample) {
        case 8:  audio_format_.sample_format = AUDIO_SAMPLE_FORMAT_8BIT; break;
        case 16: audio_format_.sample_format = AUDIO_SAMPLE_FORMAT_16BIT; break;
        default:
            printf("Unsupported bits per sample (%hu)\n", wav_info.bits_per_sample);
            return ZX_ERR_INVALID_ARGS;
    };

    audio_format_.frame_rate = wav_info.frame_rate;
    audio_format_.channels   = wav_info.channel_count;

    // Skip any extra data in the format chunk
    size_t total_wav_hdr_size = wav_info.fmt_chunk_len + offsetof(WAVHeader, format);
    if (total_wav_hdr_size < sizeof(WAVHeader)) {
        printf("Bad format chunk length in WAV header (%u)\n", wav_info.fmt_chunk_len);
        return ZX_ERR_INVALID_ARGS;
    }

    if (total_wav_hdr_size > sizeof(WAVHeader)) {
        off_t delta = total_wav_hdr_size - sizeof(WAVHeader);
        if (::lseek(fd_, delta, SEEK_CUR) < 0) {
            printf("Error while attempt to skip %zu bytes of extra WAV header\n",
                    static_cast<size_t>(delta));
            return ZX_ERR_INVALID_ARGS;
        }
    }

    // Read and skip chunks until we find the data chunk.
    RIFFChunkHeader data_hdr;
    while (true) {
        res = Read(&data_hdr, sizeof(data_hdr));
        if (res != ZX_OK) {
            printf("Failed to find DATA chunk header\n");
            return res;
        }
        data_hdr.FixupEndian();

        if (data_hdr.four_cc == DATA_FOUR_CC)
            break;

        if (::lseek(fd_, data_hdr.length, SEEK_CUR) < 0) {
            printf("Error while attempt to skip %u bytes of 0x%08x chunk\n",
                    data_hdr.length, data_hdr.four_cc);
            return ZX_ERR_INVALID_ARGS;
        }
    }

    // If the length of the data chunk is not a multiple of the frame size, log a
    // warning and truncate the length.
    uint16_t leftover;
    payload_len_ = data_hdr.length;
    leftover     = static_cast<uint16_t>(payload_len_ % wav_info.frame_size);
    if (leftover) {
        printf("WARNING: Data chunk length (%u) not a multiple of frame size (%hu)\n",
                payload_len_, wav_info.frame_size);
        payload_len_ -= leftover;
    }

    cleanup.cancel();
    return ZX_OK;
}

zx_status_t WAVSource::GetFormat(Format* out_format) {
    if (fd_ < 0)
        return ZX_ERR_BAD_STATE;

    *out_format = audio_format_;
    return ZX_OK;
}

zx_status_t WAVSource::GetFrames(void* buffer, uint32_t buf_space, uint32_t* out_packed) {
    if ((buffer == nullptr) || (out_packed == nullptr))
        return ZX_ERR_INVALID_ARGS;

    if ((fd_ < 0) || finished())
        return ZX_ERR_BAD_STATE;

    ZX_DEBUG_ASSERT(payload_played_ < payload_len_);
    uint32_t todo = fbl::min(buf_space, payload_len_ - payload_played_);
    zx_status_t res = Read(buffer, todo);
    if (res == ZX_OK) {
        payload_played_ += todo;
        *out_packed = todo;
    }

    return res;
}
