/*
* Copyright (C) 2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "config.h"
#include "ShareDataReader.h"

#include "BlobLoader.h"
#include "Document.h"
#include "SharedBuffer.h"

namespace WebCore {

ShareDataReader::ShareDataReader(CompletionHandler<void(ExceptionOr<ShareDataWithParsedURL&>)>&& completionHandler)
    : m_completionHandler(WTFMove(completionHandler))
{
    
}

ShareDataReader::~ShareDataReader()
{
    cancel();
}

void ShareDataReader::start(Document* document, ShareDataWithParsedURL&& shareData)
{
    m_filesReadSoFar = 0;
    m_shareData = WTFMove(shareData);
    int count = 0;
    m_pendingFileLoads.reserveInitialCapacity(m_shareData.shareData.files.size());
    for (auto& blob : m_shareData.shareData.files) {
        m_pendingFileLoads.uncheckedAppend(makeUniqueRef<BlobLoader>(document, *blob, [this, count, fileName = blob->name()] {
            this->didFinishLoading(count, fileName);
        }));
        count++;
    }
}

void ShareDataReader::didFinishLoading(int loadIndex, const String& fileName)
{
    if (m_pendingFileLoads[loadIndex]->errorCode()) {
        if (auto completionHandler = std::exchange(m_completionHandler, { }))
            completionHandler(Exception { AbortError, "Abort due to error while reading files."_s });
        cancel();
        return;
    }
    
    auto arrayBuffer = m_pendingFileLoads[loadIndex]->result();
    
    RawFile file;
    file.fileName = fileName;
    file.fileData = SharedBuffer::create(static_cast<const unsigned char*>(arrayBuffer->data()), arrayBuffer->byteLength());
    m_shareData.files.append(WTFMove(file));
    m_filesReadSoFar++;
    
    if (m_filesReadSoFar == static_cast<int>(m_pendingFileLoads.size())) {
        m_pendingFileLoads.clear();
        if (auto completionHandler = std::exchange(m_completionHandler, { }))
            completionHandler(m_shareData);
    }
}

void ShareDataReader::cancel()
{
    m_pendingFileLoads.clear();
}
}
