/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "OTAImageProcessorImpl.h"
#include <lib/support/CHIPMemString.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>

#ifdef BOOT_ENABLED
#include "bootutil/bootutil.h"
#include "flash_map_backend/secondary_bd.h"
#include "platform/mbed_power_mgmt.h"
#include "rtos/ThisThread.h"
#endif

using namespace ::chip::DeviceLayer::Internal;

namespace chip {

OTAImageProcessorImpl::OTAImageProcessorImpl()
{
#ifdef BOOT_ENABLED
    // Set block device - memory for image update
    mBlockDevice = get_secondary_bd();
#endif
}

int OTAImageProcessorImpl::MemoryTest()
{
    int ret = 0;
    bd_size_t read_size;
    bd_size_t program_size;
    bd_size_t erase_size;
    bd_size_t full_size;
    size_t buffer_size;
    char * buffer = nullptr;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Initialize the block device
    ret = mBlockDevice->init();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device initialization failed [%d]", ret);
        goto exit;
    }

    // Get the block device type
    ChipLogProgress(SoftwareUpdate, "Block device type: %s", mBlockDevice->get_type());

    // Get device geometry
    read_size    = mBlockDevice->get_read_size();
    program_size = mBlockDevice->get_program_size();
    erase_size   = mBlockDevice->get_erase_size();
    full_size    = mBlockDevice->size();

    ChipLogProgress(SoftwareUpdate, "--- Block device geometry ---");
    ChipLogProgress(SoftwareUpdate, "read_size:    %lld B", read_size);
    ChipLogProgress(SoftwareUpdate, "program_size: %lld B", program_size);
    ChipLogProgress(SoftwareUpdate, "erase_size:   %lld B", erase_size);
    ChipLogProgress(SoftwareUpdate, "size:         %lld B", full_size);
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Allocate a block with enough space for our data, aligned to the
    // nearest program_size. This is the minimum size necessary to write
    // data to a block.
    buffer_size = sizeof("Hello Storage!") + program_size - 1;
    buffer_size = buffer_size - (buffer_size % program_size);
    buffer      = new char[buffer_size];

    // Read what is currently stored on the block device. We haven't written
    // yet so this may be garbage
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Currently stored data ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
        }
        ChipLogProgress(SoftwareUpdate, " ");
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Write data to first block, write occurs in two parts,
    // an erase followed by a program
    ret = mBlockDevice->erase(0, erase_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device erase failed [%d]", ret);
        goto exit;
    }

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);

    // Read the data from the first block
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Stored data after erase ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
            ChipLogProgress(SoftwareUpdate, " ");
        }
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);
    // Update buffer with our string we want to store
    Platform::CopyString(buffer, buffer_size, "Hello Storage!");

    ret = mBlockDevice->program(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device program failed [%d]", ret);
        goto exit;
    }

    // Clear the buffer so we don't get old data
    memset(buffer, 0x0, buffer_size);

    // Read the data from the first block, note that the program_size must be
    // a multiple of the read_size, so we don't have to check for alignment
    ret = mBlockDevice->read(buffer, 0, buffer_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        goto exit;
    }

    ChipLogProgress(SoftwareUpdate, "--- Stored data after write ---");
    for (size_t i = 0; i < buffer_size; i += 16)
    {
        for (size_t j = 0; j < 16; j++)
        {
            if (i + j < buffer_size)
            {
                ChipLogProgress(SoftwareUpdate, "%02x ", buffer[i + j]);
            }
            else
            {
                ChipLogProgress(SoftwareUpdate, "   ");
            }
        }

        ChipLogProgress(SoftwareUpdate, " %.*s", buffer_size - i, &buffer[i]);
    }
    ChipLogProgress(SoftwareUpdate, "---\n");

    ret = strcmp(buffer, "Hello Storage!");
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Data compare failed");
    }
    else
    {
        ChipLogProgress(SoftwareUpdate, "--- MEMORY TEST PASS ---");
    }

exit:
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "--- MEMORY TEST FAILED ---");
    }

    if (buffer)
    {
        delete buffer;
    }
    // Deinitialize the block device
    ret = mBlockDevice->deinit();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block deinitialization read failed [%d]", ret);
        goto exit;
    }

    return ret;
}

CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
{
    ChipLogProgress(SoftwareUpdate, "Prepare download");
    ClearDownloadParams();
    DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Finalize()
{
    ChipLogProgress(SoftwareUpdate, "Finalize");
    DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Apply()
{
    ChipLogProgress(SoftwareUpdate, "Apply");
    DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::Abort()
{
    ChipLogProgress(SoftwareUpdate, "Abort");
    ClearDownloadParams();
    DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
};

CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
{
    ChipLogProgress(SoftwareUpdate, "Process block");
    CHIP_ERROR err = SetBlock(block);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }
    DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast<intptr_t>(this));
    return CHIP_NO_ERROR;
}

void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }
    else if (imageProcessor->mDownloader == nullptr)
    {
        ChipLogError(SoftwareUpdate, "mDownloader is null");
        return;
    }

    auto ret = imageProcessor->PrepareMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Prepare download memory failed");
        imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_INTERNAL);
        return;
    }

    ret = imageProcessor->ClearMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Clear download memory failed");
        imageProcessor->mDownloader->OnPreparedForDownload(CHIP_ERROR_INTERNAL);
        return;
    }
    imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
}

void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

    imageProcessor->mParams.totalFileBytes = imageProcessor->mParams.downloadedBytes;
    imageProcessor->ReleaseBlock();
    auto ret = imageProcessor->CloseMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Close download memory failed");
    }
    ChipLogProgress(SoftwareUpdate, "OTA image downloaded size %lldB", imageProcessor->mParams.totalFileBytes);
}

void OTAImageProcessorImpl::HandleAbort(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

    auto ret = imageProcessor->ClearMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Clear download memory failed");
    }

    ret = imageProcessor->CloseMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Close download memory failed");
    }

    imageProcessor->ReleaseBlock();
}

void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }
    else if (imageProcessor->mDownloader == nullptr)
    {
        ChipLogError(SoftwareUpdate, "mDownloader is null");
        return;
    }

    auto ret = imageProcessor->ProgramMemory();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Program download memory failed");
    }
    imageProcessor->mDownloader->FetchNextData();
}

void OTAImageProcessorImpl::HandleApply(intptr_t context)
{
    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
    if (imageProcessor == nullptr)
    {
        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
        return;
    }

#ifdef BOOT_ENABLED
    ChipLogProgress(SoftwareUpdate, "Set secondary image pending");
    auto ret = boot_set_pending_multi(/*image index*/ 0, /*permanent*/ 0);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Setting the update candidate as pending failed: %d", ret);
    }

    // Restart the device
    ChipLogProgress(SoftwareUpdate, "Device restarting....");
    rtos::ThisThread::sleep_for(3000);
    system_reset();
#endif
}

CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
{
    if (!IsSpanUsable(block))
    {
        ReleaseBlock();
        return CHIP_NO_ERROR;
    }
    if (mBlock.size() < block.size())
    {
        if (!mBlock.empty())
        {
            ReleaseBlock();
        }

        size_t buffer_size = 0;
        if (mBlockDevice)
        {
            // Aligned to the nearest program_size. This is the minimum size necessary to write data to a block.
            bd_size_t program_size = mBlockDevice->get_program_size();
            buffer_size            = block.size() + program_size - 1;
            buffer_size            = buffer_size - (buffer_size % program_size);
        }
        else
        {
            buffer_size = block.size();
        }

        uint8_t * mBlock_ptr = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(buffer_size));
        if (mBlock_ptr == nullptr)
        {
            return CHIP_ERROR_NO_MEMORY;
        }
        mBlock = MutableByteSpan(mBlock_ptr, buffer_size);
    }
    CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
{
    if (mBlock.data() != nullptr)
    {
        chip::Platform::MemoryFree(mBlock.data());
    }
    mBlock = MutableByteSpan();
    return CHIP_NO_ERROR;
}

void OTAImageProcessorImpl::ClearDownloadParams()
{
    mParams.downloadedBytes = 0;
    mParams.totalFileBytes  = 0;
}

int OTAImageProcessorImpl::PrepareMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Initialize the block device
    ret = mBlockDevice->init();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device initialization failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate, "Block device initialize");

    // Initialization read from the block device
    bd_size_t read_size = mBlockDevice->get_read_size();
    char buff[read_size];
    ret = mBlockDevice->read(&buff, 0, read_size);
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device read failed [%d]", ret);
        return ret;
    }

    return ret;
}

int OTAImageProcessorImpl::CloseMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Deinitialize the block device
    ret = mBlockDevice->deinit();
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device deinitialization failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate, "Block device deinitialization");

    return ret;
}

int OTAImageProcessorImpl::ClearMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Erase memory of block device
    ret = mBlockDevice->erase(0, mBlockDevice->size());
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Erase block device failed [%d]", ret);
        return ret;
    }

    return ret;
}

int OTAImageProcessorImpl::ProgramMemory()
{
    int ret = 0;

    if (!mBlockDevice)
    {
        ChipLogError(SoftwareUpdate, "Block device not set");
        return 1;
    }

    // Write data to memory
    ret = mBlockDevice->program(mBlock.data(), mParams.downloadedBytes, mBlock.size());
    if (ret)
    {
        ChipLogError(SoftwareUpdate, "Block device program failed [%d]", ret);
        return ret;
    }
    ChipLogProgress(SoftwareUpdate,
                    "Secondary slot program with offset: "
                    "0x%" PRIx64,
                    mParams.downloadedBytes);
    mParams.downloadedBytes += mBlock.size();

    return ret;
}

} // namespace chip
