#include "stdafx.h"
#include "MAC.h"
#include "All.h"
#include "FLACTag.h"
#include "AIFFTag.h"

namespace APE
{

CAIFFTag::CAIFFTag(const TCHAR * pFilename)
{
    /*
    m_spIO.Assign(CreateCIO());
    if (m_spIO->Open(pFilename, true) == ERROR_SUCCESS)
    {
        // get the file size
        int64 m_nFileBytes = m_spIO->GetSize();

        // get the RIFF header
        RIFF_HEADER RIFFHeader;
        RETURN_ON_ERROR(ReadSafe(m_spIO, &RIFFHeader, sizeof(RIFFHeader)))
            RIFFHeader.nBytes = ConvertU32BE(RIFFHeader.nBytes);

        // make sure the RIFF header is valid
        if (memcmp(RIFFHeader.cRIFF, "FORM", 4) != 0)
            return ERROR_INVALID_INPUT_FILE;
        if (static_cast<int64>(RIFFHeader.nBytes) != (m_nFileBytes - static_cast<int64>(sizeof(RIFF_HEADER))))
            return ERROR_INVALID_INPUT_FILE;

        // read the AIFF header
#pragma pack(push, 2)
        struct COMM_HEADER
        {
            int16 nChannels;
            uint32 nFrames;
            int16 nSampleSize;
            uint16 nSampleRateExponent;
            uint64 nSampleRateMantissa;
        };
#pragma pack(pop)

        // read AIFF header and only support AIFF
        char cAIFF[4] = { 0, 0, 0, 0 };
        RETURN_ON_ERROR(ReadSafe(m_spIO, &cAIFF[0], sizeof(cAIFF)))
            if (memcmp(cAIFF, "AIFF", 4) != 0 &&
                memcmp(cAIFF, "AIFC", 4) != 0)
            {
                // unknown type
                return ERROR_INVALID_INPUT_FILE;
            }

        // read chunks
#pragma pack(push, 1)
        struct CHUNKS
        {
            char cChunkName[4];
            uint32 nChunkBytes;
        };
#pragma pack(pop)
        COMM_HEADER Common; APE_CLEAR(Common);
        while (true)
        {
            CHUNKS Chunk; APE_CLEAR(Chunk);
            RETURN_ON_ERROR(ReadSafe(m_spIO, &Chunk, sizeof(Chunk)))
                Chunk.nChunkBytes = ConvertU32BE(Chunk.nChunkBytes);
            Chunk.nChunkBytes = (Chunk.nChunkBytes + 1) & static_cast<uint32_t>(~1L);
            bool bSeekToNextChunk = true;

            if (memcmp(Chunk.cChunkName, "COMM", 4) == 0)
            {
                // read the common chunk

                // check the size
                if (sizeof(Common) > Chunk.nChunkBytes)
                    return ERROR_INVALID_INPUT_FILE;
                RETURN_ON_ERROR(ReadSafe(m_spIO, &Common, sizeof(Common)))
                    bSeekToNextChunk = false; // don't seek since we already read

                Common.nChannels = ConvertI16BE(Common.nChannels);
                Common.nFrames = ConvertU32BE(Common.nFrames);
                Common.nSampleSize = ConvertI16BE(Common.nSampleSize);
                Common.nSampleRateExponent = ConvertU16BE(Common.nSampleRateExponent);
                Common.nSampleRateMantissa = ConvertU64BE(Common.nSampleRateMantissa);
                const double dSampleRate = GetExtendedDouble(Common.nSampleRateExponent, Common.nSampleRateMantissa);
                const uint32 nSampleRate = static_cast<uint32>(dSampleRate);
                m_bFloat = false;

                // skip rest of header
                if (Chunk.nChunkBytes > sizeof(Common))
                {
                    const int nExtraBytes = static_cast<int>(Chunk.nChunkBytes) - static_cast<int>(sizeof(Common));

                    CSmartPtr<BYTE> spBuffer(new BYTE[static_cast<size_t>(nExtraBytes)], true);
                    RETURN_ON_ERROR(ReadSafe(m_spIO, spBuffer, nExtraBytes))

                        // COMM chunks can optionally have a compression type after the last cExtra parameter and in this case "sowt" mean we're little endian (reversed from normal AIFF)
                        m_bLittleEndian = false;
                    if (nExtraBytes >= 4)
                    {
                        if (memcmp(spBuffer, "NONE", 4) == 0)
                        {
                            // this means we're a supported file
                        }
                        else if (memcmp(spBuffer, "sowt", 4) == 0)
                        {
                            m_bLittleEndian = true;
                        }
                        else if ((memcmp(spBuffer, "fl32", 4) == 0) || (memcmp(spBuffer, "FL32", 4) == 0))
                        {
                            m_bFloat = true;
#ifndef APE_SUPPORT_FLOAT_COMPRESSION
                            // 32-bit floating point data (not supported)
                            return ERROR_INVALID_INPUT_FILE;
#endif
                        }
                        else
                        {
                            // unknown encoding, so we'll error out
                            return ERROR_INVALID_INPUT_FILE;
                        }
                    }
                }

                // copy the format information to the WAVEFORMATEX passed in
                FillWaveFormatEx(&m_wfeSource, m_bFloat ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM, static_cast<int>(nSampleRate), static_cast<int>(Common.nSampleSize), static_cast<int>(Common.nChannels));
            }
            else if (memcmp(Chunk.cChunkName, "SSND", 4) == 0)
            {
                // read the SSND header
                struct SSNDHeader
                {
                    uint32 offset;
                    uint32 blocksize;
                };
                SSNDHeader Header;
                RETURN_ON_ERROR(ReadSafe(m_spIO, &Header, sizeof(Header)))
                    m_nDataBytes = static_cast<int64>(Chunk.nChunkBytes) - 8;

                // check the size
                if ((Common.nFrames > 0) && (static_cast<int64>(m_nDataBytes / Common.nFrames) != static_cast<int64>(Common.nSampleSize * Common.nChannels / 8)))
                    return ERROR_INVALID_INPUT_FILE;

                break;
            }

            if (bSeekToNextChunk)
            {
                const int nNextChunkBytes = static_cast<int>(Chunk.nChunkBytes);
                m_spIO->Seek(nNextChunkBytes, SeekFileCurrent);
            }
        }

        // make sure we found the SSND header
        if (m_nDataBytes <= 0)
            return ERROR_INVALID_INPUT_FILE;

        // calculate the header and terminating data
        m_nHeaderBytes = static_cast<uint32_t>(m_spIO->GetPosition());
        m_nTerminatingBytes = static_cast<uint32_t>(m_nFileBytes - (m_nHeaderBytes + m_nDataBytes));

        // we made it this far, everything must be cool
        //return ERROR_SUCCESS;
    }
    */
}

}
